Skip to content
Open
Prev Previous commit
Next Next commit
handle deserialization failures properly: return 400. content deseria…
…lization is NOT optional.
  • Loading branch information
Achim Adam committed Jan 27, 2014
commit cb1a81e6fd3716cf47f2e8ea4bcfa0578a93a9c7
7 changes: 5 additions & 2 deletions lib/Dancer/Handler.pm
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@ sub handle_request {
Dancer::SharedData->request($request);

# deserialize the request body if possible
$request = Dancer::Serializer->process_request($request)
if Dancer::App->current->setting('serializer');
if (Dancer::App->current->setting('serializer')) {
$request = Dancer::Serializer->process_request($request);
return $self->render_response unless $request;
}


# read cookies from client

Expand Down
9 changes: 7 additions & 2 deletions lib/Dancer/Serializer.pm
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,21 @@ sub process_request {

my $old_params = $request->params('body');

# try to deserialize
# deserialize
my $new_params;
eval {
$new_params = engine->deserialize($request->body)
};
if ($@) {
Dancer::Error->new(
code => 400,
title => "Bad request",
message => "Deserialization failed",
)->render;
Dancer::Logger::core "Unable to deserialize request body with "
. engine()
. " : \n$@";
return $request;
return;
}

if(!ref $new_params or ref $new_params ne 'HASH'){
Expand Down
81 changes: 81 additions & 0 deletions t/14_serializer/19_deserialization_failure.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use Dancer ':tests';
use Dancer::Test;
use Test::More;
use Dancer::ModuleLoader;
use LWP::UserAgent;

plan skip_all => "skip test with Test::TCP in win32" if $^O eq 'MSWin32';
plan skip_all => 'Test::TCP is needed to run this test'
unless Dancer::ModuleLoader->load('Test::TCP' => "1.30");

plan skip_all => 'JSON is needed to run this test'
unless Dancer::ModuleLoader->load('JSON');

plan tests => 3;

set serializer => 'JSON';

my $data = { foo => 'bar' };

Test::TCP::test_tcp(
client => sub {
my $port = shift;
my $ua = LWP::UserAgent->new;
my $request = HTTP::Request->new(
PUT => "http://127.0.0.1:$port/deserialization",
[
Host => 'localhost',
Content_Type => 'application/json'
],
to_json($data),
);
my $res = $ua->request($request);
ok $res->is_success, 'Successful response from server';
is_deeply from_json($res->content), $data, 'Correct content';
},
server => sub {
my $port = shift;
use Dancer ':tests';
set(
apphandler => 'Standalone',
port => $port,
show_errors => 0,
startup_info => 0,
);
put '/deserialization' => sub { $data };
Dancer->dance;
},
);

Test::TCP::test_tcp(
client => sub {
my $port = shift;
my $ua = LWP::UserAgent->new;
my $request = HTTP::Request->new(
PUT => "http://127.0.0.1:$port/deserialization",
[
Host => 'localhost',
Content_Type => 'application/json'
],
# broken JSON
'{ "foo": "bar", }',
);
my $res = $ua->request($request);
is $res->code, 400, '400 bad request';
},
server => sub {
my $port = shift;
use Dancer ':tests';
set(
apphandler => 'Standalone',
port => $port,
show_errors => 1,
startup_info => 0,
);
put '/deserialization' => sub { $data };
Dancer->dance;
},
);