Catalyst-Runtime

 view release on metacpan or  search on metacpan

lib/Catalyst/Request.pm  view on Meta::CPAN

    # we create a buffer unless one exists.

    my $stream_buffer;
    if ($self->env->{'psgix.input.buffered'}) {
        # Be paranoid about previous psgi middleware or apps that read the
        # input but didn't return the buffer to the start.
        $self->env->{'psgi.input'}->seek(0, 0);
    } else {
        $stream_buffer = Stream::Buffered->new($length);
    }

    # Check for definedness as you could read '0'
    while ( defined ( my $chunk = $self->read() ) ) {
        $self->prepare_body_chunk($chunk);
        next unless $stream_buffer;

        $stream_buffer->print($chunk)
            || die sprintf "Failed to write %d bytes to psgi.input file: $!", length( $chunk );
    }

    # Ok, we read the body.  Lets play nice for any PSGI app down the pipe

    if ($stream_buffer) {
        $self->env->{'psgix.input.buffered'} = 1;
        $self->env->{'psgi.input'} = $stream_buffer->rewind;
    } else {
        $self->env->{'psgi.input'}->seek(0, 0); # Reset the buffer for downstream middleware or apps
    }

    # paranoia against wrong Content-Length header
    my $remaining = $length - $self->_read_position;
    if ( $remaining > 0 ) {
        Catalyst::Exception->throw("Wrong Content-Length value: $length" );
    }
}

sub prepare_body_chunk {
    my ( $self, $chunk ) = @_;

    $self->_body->add($chunk);
}

sub prepare_body_parameters {
    my ( $self, $c ) = @_;
    return $self->body_parameters if $self->has_body_parameters;
    $self->prepare_body if ! $self->_has_body;

    unless($self->_body) {
      my $return = $self->_use_hash_multivalue ? Hash::MultiValue->new : {};
      $self->body_parameters($return);
      return $return;
    }

    my $params;
    my %part_data = %{$self->_body->part_data};
    if(scalar %part_data && !$c->config->{skip_complex_post_part_handling}) {
      foreach my $key (keys %part_data) {
        my $proto_value = $part_data{$key};
        my ($val, @extra) = (ref($proto_value)||'') eq 'ARRAY' ? @$proto_value : ($proto_value);

        $key = $c->_handle_param_unicode_decoding($key)
          if ($c and $c->encoding and !$c->config->{skip_body_param_unicode_decoding});

        if(@extra) {
          $params->{$key} = [map { Catalyst::Request::PartData->build_from_part_data($c, $_) } ($val,@extra)];
        } else {
          $params->{$key} = Catalyst::Request::PartData->build_from_part_data($c, $val);
        }
      }
    } else {
      $params = $self->_body->param;

      # If we have an encoding configured (like UTF-8) in general we expect a client
      # to POST with the encoding we fufilled the request in. Otherwise don't do any
      # encoding (good change wide chars could be in HTML entity style llike the old
      # days -JNAP

      # so, now that HTTP::Body prepared the body params, we gotta 'walk' the structure
      # and do any needed decoding.

      # This only does something if the encoding is set via the encoding param.  Remember
      # this is assuming the client is not bad and responds with what you provided.  In
      # general you can just use utf8 and get away with it.
      #
      # I need to see if $c is here since this also doubles as a builder for the object :(

      if($c and $c->encoding and !$c->config->{skip_body_param_unicode_decoding}) {
        $params = $c->_handle_unicode_decoding($params);
      }
    }

    my $return = $self->_use_hash_multivalue ?
        Hash::MultiValue->from_mixed($params) :
        $params;

    $self->body_parameters($return) unless $self->has_body_parameters;
    return $return;
}

sub prepare_connection {
    my ($self) = @_;

    my $env = $self->env;

    $self->address( $env->{REMOTE_ADDR} );
    $self->hostname( $env->{REMOTE_HOST} )
        if exists $env->{REMOTE_HOST};
    $self->protocol( $env->{SERVER_PROTOCOL} );
    $self->remote_user( $env->{REMOTE_USER} );
    $self->method( $env->{REQUEST_METHOD} );
    $self->secure( $env->{'psgi.url_scheme'} eq 'https' ? 1 : 0 );
}

# XXX - FIXME - method is here now, move this crap...
around parameters => sub {
    my ($orig, $self, $params) = @_;
    if ($params) {
        if ( !ref $params ) {
            $self->_log->warn(
                "Attempt to retrieve '$params' with req->params(), " .
                "you probably meant to call req->param('$params')"
            );
            $params = undef;
        }
        return $self->$orig($params);
    }
    $self->$orig();
};

has base => (
  is => 'rw',
  required => 1,
  lazy => 1,
  default => sub {
    my $self = shift;
    return $self->path if $self->has_uri;
  },
);

has _body => (
  is => 'rw', clearer => '_clear_body', predicate => '_has_body',
);
# Eugh, ugly. Should just be able to rename accessor methods to 'body'
#             and provide a custom reader..
sub body {
  my $self = shift;
  $self->prepare_body unless $self->_has_body;
  croak 'body is a reader' if scalar @_;



( run in 1.321 second using v1.01-cache-2.11-cpan-39bf76dae61 )