view release on metacpan or search on metacpan
unwind/unroll the stack for custom error reporting.
(Yves Orton)
* Added a cpanfile to allow installing local dependencies with
carton. (Mickey Nasriachi)
* GH #1260: Specify optional charset to send_file and send_as
(Russell @veryrusty Jenkins)
* PR #1162: Change skeleton template tags so skeletons can generate
applications that use Template Toolkit default tags (Jason Lewis)
* GH #1149: Fix config loading inconsistencies, support local config
files in addition to standard Dancer conf files (Jonathan Scott Duff)
* PR #1269: Stash decoded body_parameters separately from those
in Plack::Request (Russell @veryrusty Jenkins)
* GH #1253: Static middleware should send 304 Not Modified to enable
intermediate level caching. (Russell @veryrusty Jenkins)
[ DOCUMENTATION ]
* GH #608: Remove extra general COPYRIGHT notice in Tutorial.
(Sawyer X)
* Simplify upload example. (Alberto Simões, Sawyer X)
0.203001 2016-09-03 20:59:47-05:00 America/Chicago
lib/Dancer2/Core/Request.pm view on Meta::CPAN
# XXX: incompatible with Plack::Request
sub body { $_[0]->raw_body }
sub id { $_id }
# Private 'read-only' attributes for request params. See the params()
# method for the public interface.
#
# _body_params, _query_params and _route_params have setter methods that
# decode byte string to characters before setting; If you know you have
# decoded (character) params, such as output from a deserializer, you can
# set these directly in the request object hash to avoid the decode op.
sub _params { $_[0]->{'_params'} ||= $_[0]->_build_params }
sub _has_params { defined $_[0]->{'_params'} }
sub _body_params { $_[0]->{'_body_params'} ||= $_[0]->body_parameters->as_hashref_mixed }
sub _query_params { $_[0]->{'_query_params'} }
sub _set_query_params {
lib/Dancer2/Core/Request.pm view on Meta::CPAN
$self->serializer->has_request || $self->serializer->set_request($request);
my $data = $serializer->deserialize($body);
die $serializer_fail if $serializer_fail;
# Set _body_params directly rather than using the setter. Deserializiation
# returns characters and skipping the decode op in the setter ensures
# that numerical data "stays" numerical; decoding an SV that is an IV
# converts that to a PVIV. Some serializers are picky (JSON)..
$self->{_body_params} = $data;
# Set body parameters (decoded HMV)
$self->{'body_parameters'} =
Hash::MultiValue->from_mixed( is_hashref($data) ? %$data : () );
return $data;
}
sub uri { $_[0]->request_uri }
sub is_head { $_[0]->method eq 'HEAD' }
sub is_post { $_[0]->method eq 'POST' }
lib/Dancer2/Core/Request.pm view on Meta::CPAN
sub parameters {
my ( $self, $type ) = @_;
# handle a specific case
if ($type) {
my $attr = "${type}_parameters";
return $self->$attr;
}
# merge together the *decoded* parameters
$self->{'merged_parameters'} ||= do {
my $query = $self->query_parameters;
my $body = $self->body_parameters;
my $route = $self->route_parameters; # not in Plack::Request
Hash::MultiValue->new( map $_->flatten, $query, $body, $route );
};
}
sub captures { shift->params->{captures} || {} }
lib/Dancer2/Core/Request.pm view on Meta::CPAN
my $new_params = $self->params;
$new_request->{_query_params} = { %{ $self->{_query_params} || {} } };
$new_request->{query_parameters} = $self->query_parameters->clone;
for my $key ( keys %{ $params || {} } ) {
my $value = $params->{$key};
$new_params->{$key} = $value;
$new_request->{_query_params}->{$key} = $value;
$new_request->{query_parameters}->add( $key => $value );
}
# Copy params (these are already decoded)
$new_request->{_params} = $new_params;
$new_request->{_body_params} = $self->{_body_params};
$new_request->{_route_params} = $self->{_route_params};
$new_request->{headers} = $self->headers;
# Copy remaining settings
$new_request->{is_behind_proxy} = $self->{is_behind_proxy};
$new_request->{vars} = $self->{vars};
# Clone any existing decoded & cached body params. (GH#1116 GH#1269)
$new_request->{'body_parameters'} = $self->body_parameters->clone;
# Delete merged HMV parameters, allowing them to be reconstructed on first use.
delete $new_request->{'merged_parameters'};
return $new_request;
}
sub _set_route {
lib/Dancer2/Core/Request.pm view on Meta::CPAN
should not try to read C<psgi.input> by hand. C<Dancer2::Core::Request>
already did it for you and kept the raw body untouched in there.
=head2 body_data
Returns the body of the request in data form, making it possible to distinguish
between C<body_parameters>, a representation of the request parameters
(L<Hash::MultiValue>) and other forms of content.
If a serializer is set, this is the deserialized request body. Otherwise this is
the decoded body parameters (if any), or the body content itself.
=head2 content
Returns the undecoded byte string POST body.
=head2 cookies
Returns a reference to a hash containing cookies, where the keys are the names of the
cookies and values are L<Dancer2::Core::Cookie> objects.
=head2 data
If the application has a serializer and if the request has serialized
content, returns the deserialized structure as a hashref.
lib/Dancer2/Core/Request.pm view on Meta::CPAN
Return the remote host of the client. This only works with web servers configured
to do a reverse DNS lookup on the client's IP address.
=head2 request_method
Alias to the C<method> accessor, for backward-compatibility with C<CGI> interface.
=head2 request_uri
Return the raw, undecoded request URI path.
=head2 route
Return the L<route|Dancer2::Core::Route> which this request matched.
=head2 scheme
Return the scheme of the request
=head2 script_name
lib/Dancer2/Manual/Migration.pod view on Meta::CPAN
=item * Engines handle encoding consistently
All engines are now expected to handle encoding on their own. User code
is expected to be in internal Perl representation.
Therefore, all serializers, for example, should deserialize to the Perl
representation. Templates, in turn, encode to UTF-8 if requested by the
user, or by default.
One side-effect of this is that C<from_yaml> will call L<YAML>'s C<Load>
function with decoded input.
=back
=head3 Templating engine changes
Whereas in Dancer1, the following were equivalent for Template::Toolkit:
template 'foo/bar'
template '/foo/bar'
t/deserialize.t view on Meta::CPAN
}
# default back to JSON for the rest
# we're overiding a RO attribute only for this test!
Dancer2->runner->apps->[0]->set_serializer_engine(
Dancer2::Serializer::JSON->new
);
note "Decoding of mixed route and deserialized body params"; {
# Check integers from request body remain integers
# but route params get decoded.
test_psgi $app, sub {
my $cb = shift;
my @req_params = (
"/from/D\x{c3}\x{bc}sseldorf", # /from/d%C3%BCsseldorf
'Content-Type' => 'application/json',
Content => JSON::MaybeXS::encode_json({ population => 592393 }),
);
my $r = $cb->( POST @req_params );
# Watch out for hash order randomization..
is_deeply(
$r->content,
'["population",592393,"town","'."D\x{c3}\x{bc}sseldorf".'"]',
"Integer from JSON body remains integer and route params decoded",
);
};
}
# Check body is deserialized on PATCH and DELETE.
# The RFC states the behaviour for DELETE is undefined; We take the lenient
# and deserialize it.
# http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-24#section-4.3.5
note "Deserialze any body content that is allowed or undefined"; {
test_psgi $app, sub {
my $app = AppDies->to_app;
isa_ok( $app, 'CODE', 'Got app' );
test_psgi $app, sub {
my $cb = shift;
my $r = $cb->( GET '/die' );
is( $r->code, 500, '/die returns 500' );
my $out = eval { JSON->new->utf8(0)->decode($r->decoded_content) };
ok(!$@, 'JSON decoding serializer error produces no errors');
isa_ok($out, 'HASH', 'Error deserializes to a hash');
like($out->{exception}, qr/^oh no/, 'Get expected error message');
};
};
subtest 'Error with exception object' => sub {
local $@;
eval { MyTestException->throw('a test exception object') };
my $err = Dancer2::Core::Error->new(
t/issues/gh-797.t view on Meta::CPAN
subtest 'Basic response' => sub {
my $res = $test->request(
POST '/',
%headers,
Content => encode_json { foo => 'bar' }
);
is( $res->code, 200, '[POST /] Correct response code' );
my $response_data = decode_json( $res->decoded_content );
is($response_data->{foo}, 'bar', "[POST /] Correct response data");
};
subtest 'Empty POST' => sub {
my $res = $test->request( POST '/', {}, %headers );
is(
$res->code,
200,
'[POST /] Correct response code with empty post body',
);
t/request_upload.t view on Meta::CPAN
is $undef, undef, '... and non-existent upload as scalar is undef';
my @uploads = $req->upload('test_upload_file');
like $uploads[0]->content, qr|^SHOGUN|,
"content for first upload is ok, via 'upload'";
like $uploads[1]->content, qr|^SHOGUN|,
"... content for second as well";
is $req->uploads->{'test_upload_file4'}[0]->content, 'SHOGUN4',
"... content for other also good";
note "headers and decoded filename";
my $encoded_filename = encode_utf8($filename);
is_deeply $uploads[0]->headers,
{ 'Content-Disposition' =>
qq[form-data; name="test_upload_file"; filename="$encoded_filename"],
'Content-Type' => 'text/plain',
};
is $uploads[0]->filename, $filename;
note "type";
is $uploads[0]->type, 'text/plain';
t/scope_problems/session_is_cleared.t view on Meta::CPAN
ok($res1->is_success, '/normal_route does not error');
## This route should die and cause a broken state
my $res2 = $test->request(GET '/route_with_renderer_error');
ok(! $res2->is_success, '/route_with_renderer_error errors errors');
## This route will now have the same session as the previous route.
## Despite not having any cookies...
my $res3 = $test->request(GET '/normal_route');
ok($res3->is_success, '/normal_route does not error');
my $session_value = $res3->decoded_content;
isnt($session_value, "I SHOULD NOT BE IN THE NEXT SESSION",
'3rd route does not have session value from second route');
done_testing();
t/scope_problems/with_return_dies.t view on Meta::CPAN
use Test::More;
use Plack::Test;
use HTTP::Request::Common qw/GET/;
use Dancer2;
my $test = Plack::Test->create(Dancer2->psgi_app);
## This route works fine
my $res1 = $test->request(GET '/normal_route');
ok($res1->is_success, '/normal_route does not error');
my $refaddr1 = $res1->decoded_content;
## This route should die
my $res2 = $test->request(GET '/route_with_renderer_error');
ok(! $res2->is_success, '/route_with_renderer_error errors errors');
my ($refaddr2) = $res2->decoded_content =~ /Hook error: (\d+)/;
## The first route now errors
## I can't seem to force with_return to fail in this test, even though I have
## it failing in production.
## So instead I'll check the refaddr of the with_return
## If refaddr of with_return is the same between route2 and route3, then this
## demonstrates that with_return has not been cleared between the two routes
## And that /normal_route is now using the wrong with_return.
## Possibly the old with_return hasn't been cleaned up? not sure.
my $res3 = $test->request(GET '/normal_route');
ok($res3->is_success, '/normal_route does not error');
my $refaddr3 = $res3->decoded_content;
isnt($refaddr1, $refaddr3, 'The 3rd request has a different with_return from the first run');
isnt($refaddr2, $refaddr3, 'The 3rd request has a different with_return from the second run');
done_testing();