X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst.pm;h=53183edded8dd3bc52b9fd3a4bbe4af50f04bdaf;hb=8ae46e9876d7f0285d7a71eb3669a593a26ef4bb;hp=8184a98e9b26e67cb42859748cb51a7dff5dc926;hpb=68b4caec7950a4dc7ed003fe0e78f73baf81f9d3;p=catagits%2FCatalyst-Runtime.git
diff --git a/lib/Catalyst.pm b/lib/Catalyst.pm
index 8184a98..53183ed 100644
--- a/lib/Catalyst.pm
+++ b/lib/Catalyst.pm
@@ -27,7 +27,7 @@ use HTML::Entities;
use Tree::Simple qw/use_weak_refs/;
use Tree::Simple::Visitor::FindByUID;
use Class::C3::Adopt::NEXT;
-use List::MoreUtils qw/uniq/;
+use List::Util qw/uniq/;
use attributes;
use String::RewritePrefix;
use Catalyst::EngineLoader;
@@ -51,6 +51,7 @@ use Catalyst::Middleware::Stash;
use Plack::Util;
use Class::Load 'load_class';
use Encode 2.21 'decode_utf8', 'encode_utf8';
+use Scalar::Util;
BEGIN { require 5.008003; }
@@ -67,6 +68,7 @@ has request => (
my $composed_request_class = $class->composed_request_class;
return $composed_request_class->new( $self->_build_request_constructor_args);
},
+ predicate => 'has_request',
lazy => 1,
);
sub _build_request_constructor_args {
@@ -81,6 +83,8 @@ sub _build_request_constructor_args {
sub composed_request_class {
my $class = shift;
+ return $class->_composed_request_class if $class->_composed_request_class;
+
my @traits = (@{$class->request_class_traits||[]}, @{$class->config->{request_class_traits}||[]});
# For each trait listed, figure out what the namespace is. First we try the $trait
@@ -92,8 +96,14 @@ sub composed_request_class {
Class::Load::load_first_existing_class($_, $class.'::'.$trait_ns.'::'. $_, 'Catalyst::'.$trait_ns.'::'.$_)
} @traits;
- return $class->_composed_request_class ||
- $class->_composed_request_class(Moose::Util::with_traits($class->request_class, @normalized_traits));
+ if ($class->debug && scalar(@normalized_traits)) {
+ my $column_width = Catalyst::Utils::term_width() - 6;
+ my $t = Text::SimpleTable->new($column_width);
+ $t->row($_) for @normalized_traits;
+ $class->log->debug( "Composed Request Class Traits:\n" . $t->draw . "\n" );
+ }
+
+ return $class->_composed_request_class(Moose::Util::with_traits($class->request_class, @normalized_traits));
}
has response => (
@@ -104,6 +114,7 @@ has response => (
my $composed_response_class = $class->composed_response_class;
return $composed_response_class->new( $self->_build_response_constructor_args);
},
+ predicate=>'has_response',
lazy => 1,
);
sub _build_response_constructor_args {
@@ -115,6 +126,8 @@ sub _build_response_constructor_args {
sub composed_response_class {
my $class = shift;
+ return $class->_composed_response_class if $class->_composed_response_class;
+
my @traits = (@{$class->response_class_traits||[]}, @{$class->config->{response_class_traits}||[]});
my $trait_ns = 'TraitFor::Response';
@@ -122,8 +135,14 @@ sub composed_response_class {
Class::Load::load_first_existing_class($_, $class.'::'.$trait_ns.'::'. $_, 'Catalyst::'.$trait_ns.'::'.$_)
} @traits;
- return $class->_composed_response_class ||
- $class->_composed_response_class(Moose::Util::with_traits($class->response_class, @normalized_traits));
+ if ($class->debug && scalar(@normalized_traits)) {
+ my $column_width = Catalyst::Utils::term_width() - 6;
+ my $t = Text::SimpleTable->new($column_width);
+ $t->row($_) for @normalized_traits;
+ $class->log->debug( "Composed Response Class Traits:\n" . $t->draw . "\n" );
+ }
+
+ return $class->_composed_response_class(Moose::Util::with_traits($class->response_class, @normalized_traits));
}
has namespace => (is => 'rw');
@@ -148,7 +167,7 @@ our $RECURSION = 1000;
our $DETACH = Catalyst::Exception::Detach->new;
our $GO = Catalyst::Exception::Go->new;
-#I imagine that very few of these really
+#I imagine that very few of these really
#need to be class variables. if any.
#maybe we should just make them attributes with a default?
__PACKAGE__->mk_classdata($_)
@@ -166,6 +185,8 @@ __PACKAGE__->stats_class('Catalyst::Stats');
sub composed_stats_class {
my $class = shift;
+ return $class->_composed_stats_class if $class->_composed_stats_class;
+
my @traits = (@{$class->stats_class_traits||[]}, @{$class->config->{stats_class_traits}||[]});
my $trait_ns = 'TraitFor::Stats';
@@ -173,14 +194,20 @@ sub composed_stats_class {
Class::Load::load_first_existing_class($_, $class.'::'.$trait_ns.'::'. $_, 'Catalyst::'.$trait_ns.'::'.$_)
} @traits;
- return $class->_composed_stats_class ||
- $class->_composed_stats_class(Moose::Util::with_traits($class->stats_class, @normalized_traits));
+ if ($class->debug && scalar(@normalized_traits)) {
+ my $column_width = Catalyst::Utils::term_width() - 6;
+ my $t = Text::SimpleTable->new($column_width);
+ $t->row($_) for @normalized_traits;
+ $class->log->debug( "Composed Stats Class Traits:\n" . $t->draw . "\n" );
+ }
+
+ return $class->_composed_stats_class(Moose::Util::with_traits($class->stats_class, @normalized_traits));
}
__PACKAGE__->_encode_check(Encode::FB_CROAK | Encode::LEAVE_SRC);
# Remember to update this in Catalyst::Runtime as well!
-our $VERSION = '5.90104';
+our $VERSION = '5.90126';
$VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
sub import {
@@ -222,11 +249,6 @@ sub _application { $_[0] }
Catalyst - The Elegant MVC Web Application Framework
-=for html
-
-
-
=head1 SYNOPSIS
See the L distribution for comprehensive
@@ -389,6 +411,10 @@ Returns the current L object, giving access to
information about the current client request (including parameters,
cookies, HTTP headers, etc.). See L.
+There is a predicate method C that returns true if the
+request object has been created. This is something you might need to
+check if you are writing plugins that run before a request is finalized.
+
=head2 REQUEST FLOW HANDLING
=head2 $c->forward( $action [, \@arguments ] )
@@ -450,7 +476,7 @@ or stash it like so:
and access it from the stash.
-Keep in mind that the C method used is that of the caller action. So a C<$c-Edetach> inside a forwarded action would run the C method from the original action requested.
+Keep in mind that the C method used is that of the caller action. So a C<< $c->detach >> inside a forwarded action would run the C method from the original action requested.
=cut
@@ -537,6 +563,10 @@ sub go { my $c = shift; $c->dispatcher->go( $c, @_ ) }
Returns the current L object, see there for details.
+There is a predicate method C that returns true if the
+request object has been created. This is something you might need to
+check if you are writing plugins that run before a request is finalized.
+
=head2 $c->stash
Returns a hashref to the stash, which may be used to store data and pass
@@ -1412,9 +1442,9 @@ EOF
}
my @middleware = map {
- ref $_ eq 'CODE' ?
- "Inline Coderef" :
- (ref($_) .' '. ($_->can('VERSION') ? $_->VERSION || '' : '')
+ ref $_ eq 'CODE' ?
+ "Inline Coderef" :
+ (ref($_) .' '. ($_->can('VERSION') ? $_->VERSION || '' : '')
|| '') } $class->registered_middlewares;
if (@middleware) {
@@ -1473,6 +1503,11 @@ EOF
$class->log->warn("This setting is deprecated and planned to be removed in Catalyst 5.81.");
}
+ # call these so we pre setup the composed classes
+ $class->composed_request_class;
+ $class->composed_response_class;
+ $class->composed_stats_class;
+
$class->setup_finalize;
# Flush the log for good measure (in case something turned off 'autoflush' early)
@@ -1576,11 +1611,11 @@ sub uri_for {
$path .= '/';
}
- my $fragment = ((scalar(@args) && ref($args[-1]) eq 'SCALAR') ? pop @args : undef );
+ my $fragment = ((scalar(@args) && ref($args[-1]) eq 'SCALAR') ? ${pop @args} : undef );
unless(blessed $path) {
if (defined($path) and $path =~ s/#(.+)$//) {
- if(defined($1) and $fragment) {
+ if(defined($1) and defined $fragment) {
carp "Abiguious fragment declaration: You cannot define a fragment in '$path' and as an argument '$fragment'";
}
if(defined($1)) {
@@ -1615,8 +1650,9 @@ sub uri_for {
if($num_captures) {
unless($expanded_action->match_captures_constraints($c, $captures)) {
- carp "captures [@{$captures}] do not match the type constraints in actionchain ending with '$expanded_action'";
- return;
+ $c->log->debug("captures [@{$captures}] do not match the type constraints in actionchain ending with '$expanded_action'")
+ if $c->debug;
+ return undef;
}
}
@@ -1631,8 +1667,9 @@ sub uri_for {
# At this point @encoded_args is the remaining Args (all captures removed).
if($expanded_action->has_args_constraints) {
unless($expanded_action->match_args($c,\@args)) {
- carp "args [@args] do not match the type constraints in action '$expanded_action'";
- return;
+ $c->log->debug("args [@args] do not match the type constraints in action '$expanded_action'")
+ if $c->debug;
+ return undef;
}
}
}
@@ -1676,23 +1713,20 @@ sub uri_for {
# somewhat lifted from URI::_query's query_form
$query = '?'.join('&', map {
my $val = $params->{$_};
- #s/([;\/?:@&=+,\$\[\]%])/$URI::Escape::escapes{$1}/go; ## Commented out because seems to lead to double encoding - JNAP
- s/ /+/g;
- my $key = $_;
+ my $key = encode_utf8($_);
+ # using the URI::Escape pattern here so utf8 chars survive
+ $key =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
+ $key =~ s/ /+/g;
+
$val = '' unless defined $val;
(map {
- my $param = "$_";
- $param = encode_utf8($param);
+ my $param = encode_utf8($_);
# using the URI::Escape pattern here so utf8 chars survive
$param =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
$param =~ s/ /+/g;
- $key = encode_utf8($key);
- # using the URI::Escape pattern here so utf8 chars survive
- $key =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
- $key =~ s/ /+/g;
-
- "${key}=$param"; } ( ref $val eq 'ARRAY' ? @$val : $val ));
+ "${key}=$param";
+ } ( ref $val eq 'ARRAY' ? @$val : $val ));
} @keys);
}
@@ -1703,7 +1737,7 @@ sub uri_for {
if(defined $fragment) {
if(blessed $path) {
- $fragment = encode_utf8(${$fragment});
+ $fragment = encode_utf8($fragment);
$fragment =~ s/([^A-Za-z0-9\-_.!~*'() ])/$URI::Escape::escapes{$1}/go;
$fragment =~ s/ /+/g;
}
@@ -1747,7 +1781,7 @@ and it will create the URI /users/the-list.
=item \@captures_and_args?
-Optional array reference of Captures (i.e. C<req->captures>)
+Optional array reference of Captures (i.e. C or C<< $c->req->captures >>)
and arguments to the request. Usually used with L
to interpolate all the parameters in the URI.
@@ -2172,16 +2206,27 @@ sub finalize {
$c->log_response;
- if ($c->use_stats) {
- my $elapsed = $c->stats->elapsed;
- my $av = $elapsed == 0 ? '??' : sprintf '%.3f', 1 / $elapsed;
- $c->log->info(
- "Request took ${elapsed}s ($av/s)\n" . $c->stats->report . "\n" );
- }
+ $c->log_stats if $c->use_stats;
return $c->response->status;
}
+=head2 $c->log_stats
+
+Logs statistics.
+
+=cut
+
+sub log_stats {
+ my $c = shift;
+
+ my $elapsed = $c->stats->elapsed;
+ my $av = $elapsed == 0 ? '??' : sprintf '%.3f', 1 / $elapsed;
+ $c->log->info(
+ "Request took ${elapsed}s ($av/s)\n" . $c->stats->report . "\n" );
+}
+
+
=head2 $c->finalize_body
Finalizes body.
@@ -2278,7 +2323,7 @@ sub finalize_encoding {
# to do this early since encodable_response is false for this condition and we need
# to match the debug output for backcompat (there's a test for this...) -JNAP
if(
- $res->content_type_charset and $c->encoding and
+ $res->content_type_charset and $c->encoding and
(uc($c->encoding->mime_name) ne uc($res->content_type_charset))
) {
my $ct = lc($res->content_type_charset);
@@ -2292,10 +2337,14 @@ sub finalize_encoding {
(defined($res->body)) and
(ref(\$res->body) eq 'SCALAR')
) {
+ # if you are finding yourself here and your body is already encoded correctly
+ # and you want to turn this off, use $c->clear_encoding to prevent encoding
+ # at this step, or set encoding to undef in the config to do so for the whole
+ # application. See the ENCODING documentaiton for better notes.
$c->res->body( $c->encoding->encode( $c->res->body, $c->_encode_check ) );
# Set the charset if necessary. This might be a bit bonkers since encodable response
- # is false when the set charset is not the same as the encoding mimetype (maybe
+ # is false when the set charset is not the same as the encoding mimetype (maybe
# confusing action at a distance here..
# Don't try to set the charset if one already exists or if headers are already finalized
$c->res->content_type($c->res->content_type . "; charset=" . $c->encoding->mime_name)
@@ -2437,9 +2486,6 @@ sub prepare {
# VERY ugly and probably shouldn't rely on ->finalize actually working
catch {
# failed prepare is always due to an invalid request, right?
- $c->response->status(400);
- $c->response->content_type('text/plain');
- $c->response->body('Bad Request');
# Note we call finalize and then die here, which escapes
# finalize being called in the enclosing block..
# It in fact couldn't be called, as we don't return $c..
@@ -2447,11 +2493,25 @@ sub prepare {
# breaking compat for people doing crazy things (we should set
# the 400 and just return the ctx here IMO, letting finalize get called
# above...
- $c->finalize;
- die $_;
+ if ( $c->_handle_http_exception($_) ) {
+ foreach my $err (@{$c->error}) {
+ $c->log->error($err);
+ }
+ $c->clear_errors;
+ $c->log->_flush if $c->log->can('_flush');
+ $_->can('rethrow') ? $_->rethrow : croak $_;
+ } else {
+ $c->response->status(400);
+ $c->response->content_type('text/plain');
+ $c->response->body('Bad Request');
+ $c->finalize;
+ die $_;
+ }
};
$c->log_request;
+ $c->{stash} = $c->stash;
+ Scalar::Util::weaken($c->{stash});
return $c;
}
@@ -2700,9 +2760,16 @@ sub log_request_parameters {
next if ! keys %$params;
my $t = Text::SimpleTable->new( [ 35, 'Parameter' ], [ $column_width, 'Value' ] );
for my $key ( sort keys %$params ) {
- my $param = $params->{$key};
- my $value = defined($param) ? $param : '';
- $t->row( $key, ref $value eq 'ARRAY' ? ( join ', ', @$value ) : $value );
+ my @values = ();
+ if(ref $params eq 'Hash::MultiValue') {
+ @values = $params->get_all($key);
+ } else {
+ my $param = $params->{$key};
+ if( defined($param) ) {
+ @values = ref $param eq 'ARRAY' ? @$param : $param;
+ }
+ }
+ $t->row( $key.( scalar @values > 1 ? ' [multiple]' : ''), join(', ', @values) );
}
$c->log->debug( ucfirst($type) . " Parameters are:\n" . $t->draw );
}
@@ -2833,7 +2900,7 @@ We try each possible role in turn (and throw an error if none load)
The namespace part 'TraitFor::Request' was chosen to assist in backwards
compatibility with L which previously provided
these features in a stand alone package.
-
+
=head2 $app->composed_request_class
This is the request class which has been composed with any request_class_traits.
@@ -3193,7 +3260,7 @@ sub setup_component {
$class->components->{ $component } = $class->setup_component($component);
}
- return $instance;
+ return $instance;
}
=head2 $app->config_for( $component_name )
@@ -3208,7 +3275,7 @@ component or component object. Example:
my $config = MyApp->config_for('MyApp::Model::Foo');
-In this case $config is the hashref C< {a=>1, b=>2} >.
+In this case $config is the hashref C<< {a=>1, b=>2} >>.
This is also handy for looking up configuration for a plugin, to make sure you follow
existing L standards for where a plugin should put its configuration.
@@ -3318,7 +3385,7 @@ sub setup_engine {
return;
}
-## This exists just to supply a prebuild psgi app for mod_perl and for the
+## This exists just to supply a prebuild psgi app for mod_perl and for the
## build in server support (back compat support for pre psgi port behavior).
## This is so that we don't build a new psgi app for each request when using
## the mod_perl handler or the built in servers (http and fcgi, etc).
@@ -3335,7 +3402,7 @@ sub _finalized_psgi_app {
}
## Look for a psgi file like 'myapp_web.psgi' (if the app is MyApp::Web) in the
-## home directory and load that and return it (just assume it is doing the
+## home directory and load that and return it (just assume it is doing the
## right thing :) ). If that does not exist, call $app->psgi_app, wrap that
## in default_middleware and return it ( this is for backward compatibility
## with pre psgi port behavior ).
@@ -3421,7 +3488,7 @@ sub apply_default_middlewares {
condition => sub {
my ($env) = @_;
return if $app->config->{ignore_frontend_proxy};
- return $env->{REMOTE_ADDR} eq '127.0.0.1';
+ return $env->{REMOTE_ADDR} && $env->{REMOTE_ADDR} eq '127.0.0.1';
},
);
}
@@ -3533,15 +3600,44 @@ sub setup_encoding {
=head2 handle_unicode_encoding_exception
-Hook to let you customize how encoding errors are handled. By default
-we just throw an exception. Receives a hashref of debug information.
-Example:
+Hook to let you customize how encoding errors are handled. By default
+we just throw an exception and the default error page will pick it up.
+Receives a hashref of debug information. Example of call (from the
+Catalyst internals):
- $c->handle_unicode_encoding_exception({
+ my $decoded_after_fail = $c->handle_unicode_encoding_exception({
param_value => $value,
error_msg => $_,
- encoding_step => 'params',
- });
+ encoding_step => 'params',
+ });
+
+The calling code expects to receive a decoded string or an exception.
+
+You can override this for custom handling of unicode errors. By
+default we just die. If you want a custom response here, one approach
+is to throw an HTTP style exception, instead of returning a decoded
+string or throwing a generic exception.
+
+ sub handle_unicode_encoding_exception {
+ my ($c, $params) = @_;
+ HTTP::Exception::BAD_REQUEST->throw(status_message=>$params->{error_msg});
+ }
+
+Alternatively you can 'catch' the error, stash it and write handling code later
+in your application:
+
+ sub handle_unicode_encoding_exception {
+ my ($c, $params) = @_;
+ $c->stash(BAD_UNICODE_DATA=>$params);
+ # return a dummy string.
+ return 1;
+ }
+
+NOTE: Please keep in mind that once an error like this occurs,
+the request setup is still ongoing, which means the state of C<$c> and
+related context parts like the request and response may not be setup
+up correctly (since we haven't finished the setup yet). If you throw
+an exception the setup is aborted.
=cut
@@ -3582,16 +3678,20 @@ sub _handle_unicode_decoding {
}
sub _handle_param_unicode_decoding {
- my ( $self, $value ) = @_;
+ my ( $self, $value, $check ) = @_;
return unless defined $value; # not in love with just ignoring undefs - jnap
return $value if blessed($value); #don't decode when the value is an object.
my $enc = $self->encoding;
+
+ return $value unless $enc; # don't decode if no encoding is specified
+
+ $check ||= $self->_encode_check;
return try {
- $enc->decode( $value, $self->_encode_check );
+ $enc->decode( $value, $check);
}
catch {
- $self->handle_unicode_encoding_exception({
+ return $self->handle_unicode_encoding_exception({
param_value => $value,
error_msg => $_,
encoding_step => 'params',
@@ -3937,14 +4037,14 @@ only two default data handlers, for 'application/json' and an alternative to
L or via L IF you've installed it.
The 'application/json' data handler is used to parse incoming JSON into a Perl
-data structure. It used either L or L, depending on which
-is installed. This allows you to fail back to L, which is a Pure Perl
-JSON decoder, and has the smallest dependency impact.
+data structure. It uses L. This allows you to fail back to
+L, which is a Pure Perl JSON decoder, and has the smallest dependency
+impact.
Because we don't wish to add more dependencies to L, if you wish to
-use this new feature we recommend installing L or L in
-order to get the best performance. You should add either to your dependency
-list (Makefile.PL, dist.ini, cpanfile, etc.)
+use this new feature we recommend installing L in order to get
+the best performance. You should add either to your dependency list
+(Makefile.PL, dist.ini, cpanfile, etc.)
=cut
@@ -3979,12 +4079,12 @@ sub default_data_handlers {
},
'application/json' => sub {
my ($fh, $req) = @_;
- my $parser = Class::Load::load_first_existing_class('JSON::MaybeXS', 'JSON');
+ require JSON::MaybeXS;
my $slurped;
- return eval {
+ return eval {
local $/;
$slurped = $fh->getline;
- $parser->can("decode_json")->($slurped); # decode_json does utf8 decoding for us
+ JSON::MaybeXS::decode_json($slurped); # decode_json does utf8 decoding for us
} || Catalyst::Exception->throw(sprintf "Error Parsing POST '%s', Error: %s", (defined($slurped) ? $slurped : 'undef') ,$@);
},
};
@@ -4018,7 +4118,7 @@ L, but can be set otherwise with
L<< stats_class|/"$c->stats_class" >>.
Even if L<< -Stats|/"-Stats" >> is not enabled, the stats object is still
-available. By enabling it with C< $c->stats->enabled(1) >, it can be used to
+available. By enabling it with C<< $c->stats->enabled(1) >>, it can be used to
profile explicitly, although MyApp.pm still won't profile nor output anything
by itself.
@@ -4226,18 +4326,20 @@ value to undef.
C
-When there is an error in an action chain, the default behavior is to continue
-processing the remaining actions and then catch the error upon chain end. This
-can lead to running actions when the application is in an unexpected state. If
-you have this issue, setting this config value to true will promptly exit a
-chain when there is an error raised in any action (thus terminating the chain
-early.)
+Defaults to true.
-use like:
+When there is an error in an action chain, the default behavior is to
+abort the processing of the remaining actions to avoid running them
+when the application is in an unexpected state.
- __PACKAGE__->config(abort_chain_on_error_fix => 1);
+Before version 5.90070, the default used to be false. To keep the old
+behaviour, you can explicitly set the value to false. E.g.
+
+ __PACKAGE__->config(abort_chain_on_error_fix => 0);
+
+If this setting is set to false, then the remaining actions are
+performed and the error is caught at the end of the chain.
-In the future this might become the default behavior.
=item *
@@ -4268,7 +4370,7 @@ that does not contain uploads, but instead contains inlined complex data
(very uncommon) we cannot reliably convert that into field => value pairs. So
instead we create an instance of L. If this causes
issue for you, you can disable this by setting C
-to true (default is false).
+to true (default is false).
=item *
@@ -4289,11 +4391,19 @@ request URL query or keywords. Most readings of the relevant specifications
suggest these should be UTF-* encoded, which is the default that L
will use, however if you are creating a lot of URLs manually or have external
evil clients, this might cause you trouble. If you find the changes introduced
-in Catalyst version 5.90080+ break some of your query code, you may disable
+in Catalyst version 5.90080+ break some of your query code, you may disable
the UTF-8 decoding globally using this configuration.
-This setting takes precedence over C and
-C
+This setting takes precedence over C
+
+=item *
+
+C
+
+Catalyst versions 5.90080 - 5.90106 would decode query parts of an incoming
+request but would not raise an exception when the decoding failed due to
+incorrect unicode. It now does, but if this change is giving you trouble
+you may disable it by setting this configuration to true.
=item *
@@ -4304,15 +4414,6 @@ is our reading of the relevant specifications. This setting allows one to
specify a fixed value for how to decode your query. You might need this if
you are doing a lot of custom encoding of your URLs and not using UTF-8.
-This setting take precedence over C.
-
-=item *
-
-C
-
-Setting this to true will default your query decoding to whatever your
-general global encoding is (the default is UTF-8).
-
=item *
C
@@ -4507,21 +4608,21 @@ option, C, which lets you associate a content type with a coderef
that parses that content type into something Perl can readily access.
package MyApp::Web;
-
+
use Catalyst;
- use JSON::Maybe;
-
+ use JSON::MaybeXS;
+
__PACKAGE__->config(
data_handlers => {
'application/json' => sub { local $/; decode_json $_->getline },
},
## Any other configuration.
);
-
+
__PACKAGE__->setup;
By default L comes with a generic JSON data handler similar to the
-example given above, which uses L to provide either L
+example given above, which uses L to provide either L
(a pure Perl, dependency free JSON parser) or L if you have
it installed (if you want the faster XS parser, add it to you project Makefile.PL
or dist.ini, cpanfile, etc.)
@@ -4543,12 +4644,12 @@ arrayref under the configuration key C. Here's an example
with details to follow:
package MyApp::Web;
-
+
use Catalyst;
use Plack::Middleware::StackTrace;
-
+
my $stacktrace_middleware = Plack::Middleware::StackTrace->new;
-
+
__PACKAGE__->config(
'psgi_middleware', [
'Debug',
@@ -4565,7 +4666,7 @@ with details to follow:
},
],
);
-
+
__PACKAGE__->setup;
So the general form is:
@@ -4591,26 +4692,26 @@ middleware will wrap closer to the application). Keep this in mind since in
some cases the order of middleware is important.
The two approaches are not exclusive.
-
+
=over 4
-
+
=item Middleware Object
-
+
An already initialized object that conforms to the L
specification:
-
+
my $stacktrace_middleware = Plack::Middleware::StackTrace->new;
-
+
__PACKAGE__->config(
'psgi_middleware', [
$stacktrace_middleware,
]);
-
-
+
+
=item coderef
-
+
A coderef that is an inlined middleware:
-
+
__PACKAGE__->config(
'psgi_middleware', [
sub {
@@ -4627,11 +4728,11 @@ A coderef that is an inlined middleware:
},
},
]);
-
-
-
+
+
+
=item a scalar
-
+
We assume the scalar refers to a namespace after normalizing it using the
following rules:
@@ -4662,12 +4763,12 @@ Examples:
'+MyApp::Custom', ## MyApp::Custom->wrap
],
);
-
+
=item a scalar followed by a hashref
-
+
Just like the previous, except the following C is used as arguments
to initialize the middleware object.
-
+
__PACKAGE__->config(
'psgi_middleware', [
'Session' => {store => 'File'},
@@ -4692,6 +4793,11 @@ the encoding configuration to undef.
This is recommended for temporary backwards compatibility only.
+To turn it off for a single request use the L
+method to turn off encoding for this request. This can be useful
+when you are setting the body to be an arbitrary block of bytes,
+especially if that block happens to be a block of UTF8 text.
+
Encoding is automatically applied when the content-type is set to
a type that can be encoded. Currently we encode when the content type
matches the following regular expression:
@@ -4814,7 +4920,7 @@ andrewalker: André Walker
Andrew Bramble
-Andrew Ford EA.Ford@ford-mason.co.ukE
+Andrew Ford
Andrew Ruthven
@@ -4828,19 +4934,19 @@ Caelum: Rafael Kitover
chansen: Christian Hansen
-Chase Venters C
+Chase Venters
chicks: Christopher Hicks
-Chisel Wright C
+Chisel Wright
-Danijel Milicevic C
+Danijel Milicevic
davewood: David Schmidt
-David Kamholz Edkamholz@cpan.orgE
+David Kamholz
-David Naughton, C
+David Naughton
David E. Wheeler
@@ -4862,7 +4968,7 @@ gabb: Danijel Milicevic
Gary Ashton Jones
-Gavin Henry C
+Gavin Henry
Geoff Richards
@@ -4874,7 +4980,7 @@ ilmari: Dagfinn Ilmari Mannsåker
jcamacho: Juan Camacho
-jester: Jesse Sheidlower C
+jester: Jesse Sheidlower
jhannah: Jay Hannah
@@ -4884,9 +4990,9 @@ Johan Lindstrom
jon: Jon Schutz
-Jonathan Rockway C<< >>
+Jonathan Rockway
-Kieren Diment C
+Kieren Diment
konobi: Scott McWhirter
@@ -4922,7 +5028,11 @@ rafl: Florian Ragwitz
random: Roland Lammel
-Robert Sedlacek C<< >>
+revmischa: Mischa Spiegelmock
+
+Robert Sedlacek
+
+rrwo: Robert Rothenberg
SpiceMan: Marcel Montes
@@ -4936,17 +5046,17 @@ Ulf Edvinsson
vanstyn: Henry Van Styn
-Viljo Marrandi C
+Viljo Marrandi
-Will Hawes C
+Will Hawes
willert: Sebastian Willert
wreis: Wallace Reis
-Yuval Kogman, C
+Yuval Kogman
-rainboxx: Matthias Dietrich, C
+rainboxx: Matthias Dietrich
dd070: Dhaval Dhanani