Return raw body for UrlEncoded requests.
David Precious [Mon, 7 Mar 2016 23:06:36 +0000 (23:06 +0000)]
This is for RT #111876:
https://rt.cpan.org/Public/Bug/Display.html?id=111876

We currently return a body filehandle for OctetStream requests, but not for
UrlEncoded requests, which causes surprises - for e.g. Dancer1 issue:
https://github.com/PerlDancer/Dancer/issues/1140

This change makes parsed UrlEncoded requests store the "raw" body (after parsing
out chunking etc) in $self->body, so the caller can get a filehandle for it just
like they would for an OctetStream request.

Tests updated to expect this new behaviour.

TODO: Decide if we need MultiPart to expose a raw body for consistency (would
anyone ever want the overall raw body for a MultiPart request?) and if so,
cobble together the request as it was (but not storing the form params part to
disk for security)

dist.ini
lib/HTTP/Body/UrlEncoded.pm
t/05urlencoded.t
t/data/urlencoded/001-results.pml
t/data/urlencoded/002-results.pml
t/data/urlencoded/003-results.pml
t/data/urlencoded/004-results.pml
t/data/urlencoded/005-results.pml
t/data/urlencoded/006-results.pml

index 57e8b1e..db196a8 100644 (file)
--- a/dist.ini
+++ b/dist.ini
@@ -20,6 +20,7 @@ Carp            = 0
 File::Temp      = 0.14
 HTTP::Headers   = 0
 IO::File        = 1.14
+IO::Handle::Util = 0.01
 Digest::MD5     = 0
 
 [Prereqs / TestRequires]
index aacef3b..3f45965 100644 (file)
@@ -3,6 +3,7 @@ package HTTP::Body::UrlEncoded;
 use strict;
 use base 'HTTP::Body';
 use bytes;
+use IO::Handle::Util;
 
 our $DECODE = qr/%([0-9a-fA-F]{2})/;
 
@@ -37,6 +38,11 @@ sub spin {
     my $self = shift;
 
     return unless $self->length == $self->content_length;
+
+    # Store a copy of the raw request that the body() method can return
+    # see RT #111876 
+    my $body_content = $self->{buffer};
+    $self->body(IO::Handle::Util::io_from_any($body_content));
     
     # I tested parsing this using APR::Request, but perl is faster
     # Pure-Perl    2560/s
index 8654b00..327c629 100644 (file)
@@ -31,7 +31,7 @@ for ( my $i = 1; $i <= 6; $i++ ) {
         $body->add($buffer);
     }
 
-    is_deeply( $body->body, $results->{body}, "$test UrlEncoded body" );
+    is_deeply( readfh($body->body), $results->{body}, "$test UrlEncoded body" );
     is_deeply( $body->param, $results->{param}, "$test UrlEncoded param" );
        is_deeply( $body->param_order, $results->{param_order} ? $results->{param_order} : [], "$test UrlEncoded param_order" );
     is_deeply( $body->upload, $results->{upload}, "$test UrlEncoded upload" );
@@ -46,3 +46,9 @@ for ( my $i = 1; $i <= 6; $i++ ) {
         is( $body->trailing_headers->header('Content-MD5'), md5_hex($buf), "$test trailing header ok" );
     }
 }
+
+sub readfh {
+    my $fh = shift or die "readfh requires a filehandle";
+    $fh->seek(0,0) or die "Failed to seek";
+    return join "", $fh->getlines;
+}
index 0fd5ba2..eefa71d 100644 (file)
@@ -1,5 +1,5 @@
 {
-  "body" => undef,
+  "body" => "text1=Ratione+accusamus+aspernatur+aliquam&text2=%C3%A5%C3%A4%C3%B6%C3%A5%C3%A4%C3%B6&select=A&select=B&textarea=Voluptatem+cumque+voluptate+sit+recusandae+at.+Et+quas+facere+rerum+unde+esse.+Sit+est+et+voluptatem.+Vel+temporibus+velit+neque+odio+non.%0D%0A%0D%0AMolestias+rerum+ut+sapiente+facere+repellendus+illo.+Eum+nulla+quis+aut.+Quidem+voluptas+vitae+ipsam+officia+voluptatibus+eveniet.+Aspernatur+cupiditate+ratione+aliquam+quidem+corrupti.+Eos+sunt+rerum+non+optio+culpa.&encoding=foo%3Dbar",
   "upload" => {},
   "param" => {
     "text2" => "\303\245\303\244\303\266\303\245\303\244\303\266",
index 5461aa5..543d722 100644 (file)
@@ -1,5 +1,5 @@
 {
-  "body" => undef,
+  "body" => "one=foo&two=bar",
   "upload" => {},
   "param" => {
     "one" => "foo",
index 0fd5ba2..eefa71d 100644 (file)
@@ -1,5 +1,5 @@
 {
-  "body" => undef,
+  "body" => "text1=Ratione+accusamus+aspernatur+aliquam&text2=%C3%A5%C3%A4%C3%B6%C3%A5%C3%A4%C3%B6&select=A&select=B&textarea=Voluptatem+cumque+voluptate+sit+recusandae+at.+Et+quas+facere+rerum+unde+esse.+Sit+est+et+voluptatem.+Vel+temporibus+velit+neque+odio+non.%0D%0A%0D%0AMolestias+rerum+ut+sapiente+facere+repellendus+illo.+Eum+nulla+quis+aut.+Quidem+voluptas+vitae+ipsam+officia+voluptatibus+eveniet.+Aspernatur+cupiditate+ratione+aliquam+quidem+corrupti.+Eos+sunt+rerum+non+optio+culpa.&encoding=foo%3Dbar",
   "upload" => {},
   "param" => {
     "text2" => "\303\245\303\244\303\266\303\245\303\244\303\266",
index 1cd75c1..0527138 100644 (file)
@@ -1,5 +1,5 @@
 {
-  "body" => undef,
+  "body" => "one=foo; two=bar",
   "upload" => {},
   "param" => {
     "one" => "foo",
index 1cd75c1..7babbdf 100644 (file)
@@ -1,5 +1,5 @@
 {
-  "body" => undef,
+  "body" => "one=foo;two=bar",
   "upload" => {},
   "param" => {
     "one" => "foo",
index 1a13c7e..bc9bc1c 100644 (file)
@@ -1,5 +1,5 @@
 {
-  "body" => undef,
+  "body" => "one=foo;two=bar=bam",
   "upload" => {},
   "param" => {
     "one" => "foo",