Dancer icon indicating copy to clipboard operation
Dancer copied to clipboard

forward()ed POST request loses body?

Open bigpresh opened this issue 2 years ago • 3 comments

Running this simple test case app, which outputs the request body, forward()s to another route and outputs the request body again:

#!/usr/bin/env perl

use 5.012;

use Dancer;
use DDP;

set serializer => 'JSON';


post '/foo' => sub {
    warn "foo running";
    p request->body;
    forward '/bar';
};

post '/bar' => sub {
    warn "Bar running";
    p request->body;
    return "Response from bar";
};

dance;

and hitting it with curl:

[davidp@supernova:~]$ curl http://localhost:3000/foo -H "Content-Type: application/json" -d '{"beer":true}'
Response from bar 

it outputs:

[davidp@supernova:~/tmp/dancer-forward-testcase]$ perl test.pl
>> Dancer 1.3513 server 367711 listening on http://0.0.0.0:3000
== Entering the development dance floor ...
foo running at test.pl line 12.
"{\"beer\":true}"
Bar running at test.pl line 18.
""

Reported by @fleetfootmike - thanks Mike!

bigpresh avatar Mar 02 '22 21:03 bigpresh

Ah, Dancer::Request->forward() doesn't copy the raw body over, but it does copy the deserialized params over, so dumping the deserialised value:

#!/usr/bin/env perl

use 5.012;

use Dancer;
use DDP;

set serializer => 'JSON';


post '/foo' => sub {
    warn "foo running";
    p request->body;
    p params->{beer}, as => 'beer in foo';
    forward '/bar';
};

post '/bar' => sub {
    warn "Bar running";
    p request->body;
    p params->{beer}, as => 'beer in bar';
    return "Response from bar";
};

dance;

shows that params->{beer} is still set after the forward:

[davidp@supernova:~/tmp/dancer-forward-testcase]$ perl test.pl
>> Dancer 1.3513 server 370232 listening on http://0.0.0.0:3000
== Entering the development dance floor ...
foo running at test.pl line 12.
"{\"beer\":true}"
beer in foo
1 (JSON::PP::Boolean) (read-only)
Bar running at test.pl line 19.
""
beer in bar
1 (JSON::PP::Boolean) (read-only)

bigpresh avatar Mar 02 '22 21:03 bigpresh

So, the impact looks limited - params will be retained etc, but the raw body may not be.

@fleetfootmike points out that it also causes a spurious deserialisation error at loglevel core, caused by the body being empty:

[373113]  core @0.000080> request: POST /bar from 127.0.0.1 in /usr/local/share/perl/5.32.1/Dancer/Handler.pm l. 58
[373113]  core @0.000285> [hit #2]Unable to deserialize request body with Dancer::Serializer::JSON=HASH(0x556cf43f7970) : 
malformed JSON string, neither tag, array, object, number, string or atom, at character offset 0 (before "(end of string)") at /usr/share/perl5/JSON.pm line 190. in /usr/local/share/perl/5.32.1/Dancer/Serializer.pm l. 102

One possibly-reasonable solution to the spurious error would be for Dancer::Serializer->process_request to not attempt to deserialize an empty body... one would assume that shouldn't break anything for anyone...

bigpresh avatar Mar 02 '22 21:03 bigpresh

The lack of the body on a forwarded request is the real issue, though.

OTTOMH, a simple fix should be to add ``$new_request->{_http_body} = $request->{_http_body}toD::Request->forward()`

bigpresh avatar Mar 02 '22 22:03 bigpresh