Move prepare_parametrs to be the builder.
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Request.pm
index 1f7465c..ee7f64b 100644 (file)
@@ -101,10 +101,9 @@ has uploads => (
 );
 
 has parameters => (
-  is => 'rw',
-  required => 1,
-  lazy => 1,
-  default => sub { {} },
+    is => 'rw',
+    lazy => 1,
+    builder => 'prepare_parameters',
 );
 
 # TODO:
@@ -115,11 +114,103 @@ has parameters => (
 #  these lazy build from there and kill all the direct hash access
 #  in Catalyst.pm and Engine.pm?
 
-before $_ => sub {
+sub prepare_parameters {
+    my ( $self ) = @_;
+
+    $self->prepare_body;
+    my $parameters = {};
+    my $body_parameters = $self->body_parameters;
+    my $query_parameters = $self->query_parameters;
+    # We copy, no references
+    foreach my $name (keys %$query_parameters) {
+        my $param = $query_parameters->{$name};
+        $parameters->{$name} = ref $param eq 'ARRAY' ? [ @$param ] : $param;
+    }
+
+    # Merge query and body parameters
+    foreach my $name (keys %$body_parameters) {
+        my $param = $body_parameters->{$name};
+        my @values = ref $param eq 'ARRAY' ? @$param : ($param);
+        if ( my $existing = $parameters->{$name} ) {
+          unshift(@values, (ref $existing eq 'ARRAY' ? @$existing : $existing));
+        }
+        $parameters->{$name} = @values > 1 ? \@values : $values[0];
+    }
+    $parameters;
+}
+
+before body_parameters => sub {
     my ($self) = @_;
-    my $context = $self->_context || return;
-    $context->prepare_body;
-} for qw/parameters body_parameters/;
+    $self->prepare_body;
+    $self->prepare_body_parameters;
+};
+
+=head2 $self->prepare_body()
+
+sets up the L<Catalyst::Request> object body using L<HTTP::Body>
+
+=cut
+
+has _uploadtmp => (
+    is => 'ro',
+    predicate => '_has_uploadtmp',
+);
+
+sub prepare_body {
+    my ( $self ) = @_;
+
+    if ( my $length = $self->_read_length ) {
+        unless ( $self->_body ) {
+            my $type = $self->header('Content-Type');
+            $self->_body(HTTP::Body->new( $type, $length ));
+            $self->_body->cleanup(1); # Make extra sure!
+            $self->_body->tmpdir( $self->_uploadtmp )
+              if $self->_has_uploadtmp;
+        }
+
+        # Check for definedness as you could read '0'
+        while ( defined ( my $buffer = $self->read() ) ) {
+            $self->prepare_body_chunk($buffer);
+        }
+
+        # paranoia against wrong Content-Length header
+        my $remaining = $length - $self->_read_position;
+        if ( $remaining > 0 ) {
+            Catalyst::Exception->throw(
+                "Wrong Content-Length value: $length" );
+        }
+    }
+    else {
+        # Defined but will cause all body code to be skipped
+        $self->_body(0);
+    }
+}
+
+=head2 $self->prepare_body_chunk()
+
+Add a chunk to the request body.
+
+=cut
+
+sub prepare_body_chunk {
+    my ( $self, $chunk ) = @_;
+
+    $self->_body->add($chunk);
+}
+
+=head2 $self->prepare_body_parameters()
+
+Sets up parameters from body.
+
+=cut
+
+sub prepare_body_parameters {
+    my ( $self ) = @_;
+
+    return unless $self->_body;
+
+    $self->{body_parameters} = $self->_body->param; # FIXME!! Recursion here.
+}
 
 around parameters => sub {
     my ($orig, $self, $params) = @_;
@@ -153,7 +244,7 @@ has _body => (
 #             and provide a custom reader..
 sub body {
   my $self = shift;
-  $self->_context->prepare_body();
+  $self->prepare_body();
   croak 'body is a reader' if scalar @_;
   return blessed $self->_body ? $self->_body->body : $self->_body;
 }