You may use the application configuration setting "use_chained_args_0_special_case"
to disable this new behavior, if you must for back-compat reasons.
- Added PATCH HTTP Method action attribute shortcut.
+ - Several new configuration options aimed to give improved backwards compatibility
+ for when your URL query parameters or keywords have non UTF-8 encodings.
+ See Catalyst::Upgrading.
5.90084 - 2015-02-23
- Small change to the way body parameters are created in order to prevent
=item *
+C<do_not_decode_query>
+
+If true, then do not try to character decode any wide characters in your
+request URL query or keywords. Most readings of the relevent specifications
+suggest these should be UTF-* encoded, which is the default that L<Catalyst>
+will use, hwoever 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
+the UTF-8 decoding globally using this configuration.
+
+This setting takes precedence over C<default_query_encoding> and
+C<decode_query_using_global_encoding>
+
+=item *
+
+C<default_query_encoding>
+
+By default we decode query and keywords in your request URL using UTF-8, which
+is our reading of the relevent 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<decode_query_using_global_encoding>.
+
+=item *
+
+C<decode_query_using_global_encoding>
+
+Setting this to true will default your query decoding to whatever your
+general global encoding is (the default is UTF-8).
+
+=item *
+
C<use_chained_args_0_special_case>
In older versions of Catalyst, when more than one action matched the same path
use HTTP::Headers;
use Plack::Loader;
use Catalyst::EngineLoader;
-use Encode 2.21 'decode_utf8';
+use Encode 2.21 'decode_utf8', 'encode', 'decode';
use Plack::Request::Upload;
use Hash::MultiValue;
use namespace::clean -except => 'meta';
sub prepare_query_parameters {
my ($self, $c) = @_;
my $env = $c->request->env;
+ my $do_not_decode_query = $c->config->{do_not_decode_query};
+ my $default_query_encoding = $c->config->{default_query_encoding} ||
+ ($c->config->{decode_query_using_global_encoding} ?
+ $c->encoding : 'UTF-8');
+
+ my $decoder = sub {
+ my $str = shift;
+ return $str if $do_not_decode_query;
+ return $str unless $default_query_encoding;
+ return decode( $default_query_encoding, $str);
+ };
my $query_string = exists $env->{QUERY_STRING}
? $env->{QUERY_STRING}
# (yes, index() is faster than a regex :))
if ( index( $query_string, '=' ) < 0 ) {
my $keywords = $self->unescape_uri($query_string);
- $keywords = decode_utf8 $keywords;
+ $keywords = $decoder->($keywords);
$c->request->query_keywords($keywords);
return;
}
$query_string =~ s/\A[&;]+//;
my $p = Hash::MultiValue->new(
- map { defined $_ ? decode_utf8($self->unescape_uri($_)) : $_ }
+ map { defined $_ ? $decoder->($self->unescape_uri($_)) : $_ }
map { ( split /=/, $_, 2 )[0,1] } # slice forces two elements
split /[&;]+/, $query_string
);
application configuration setting "use_chained_args_0_special_case" to true and
that will revert you code to the previous behavior.
+=head2 More backwards compatibility options with UTF-8 changes
+
+In order to give better backwards compatiblity with the 5.90080+ UTF-8 changes
+we've added several configuration options around control of how we try to decode
+your URL keywords / query parameters.
+
+C<do_not_decode_query>
+
+If true, then do not try to character decode any wide characters in your
+request URL query or keywords. Most readings of the relevent specifications
+suggest these should be UTF-* encoded, which is the default that L<Catalyst>
+will use, hwoever 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
+the UTF-8 decoding globally using this configuration.
+
+This setting takes precedence over C<default_query_encoding> and
+C<decode_query_using_global_encoding>
+
+C<default_query_encoding>
+
+By default we decode query and keywords in your request URL using UTF-8, which
+is our reading of the relevent 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<decode_query_using_global_encoding>.
+
+C<decode_query_using_global_encoding>
+
+Setting this to true will default your query decoding to whatever your
+general global encoding is (the default is UTF-8).
+
+
=head1 Upgrading to Catalyst 5.90080
UTF8 encoding is now default. For temporary backwards compatibility, if this
--- /dev/null
+use utf8;
+use warnings;
+use strict;
+
+# For reported: https://rt.cpan.org/Ticket/Display.html?id=103063
+
+{
+ package MyApp::Controller::Root;
+ $INC{'MyApp/Controller/Root.pm'} = __FILE__;
+
+ use base 'Catalyst::Controller';
+
+ sub example :Local Args(0) {
+ pop->stash->{testing1} = 'testing2';
+ }
+
+ package MyApp;
+ use Catalyst;
+
+ #MyApp->config(decode_query_using_global_encoding=>1, encoding => 'SHIFT_JIS');
+ #MyApp->config(do_not_decode_query=>1);
+ #MyApp->config(decode_query_using_global_encoding=>1, encoding => undef);
+ MyApp->config(default_query_encoding=>'SHIFT_JIS');
+
+ MyApp->setup;
+}
+
+use Test::More;
+use Catalyst::Test 'MyApp';
+use Encode;
+use HTTP::Request::Common;
+
+{
+ my $shiftjs = 'test テスト';
+ my $encoded = Encode::encode('SHIFT_JIS', $shiftjs);
+
+ ok my $req = GET "/root/example?a=$encoded";
+ my ($res, $c) = ctx_request $req;
+
+ is $c->req->query_parameters->{'a'}, $shiftjs, 'got expected value';
+}
+
+
+done_testing;
+
}
+{
+ my $shiftjs = 'test テスト';
+ my $encoded = Encode::encode('UTF-8', $shiftjs);
+
+ ok my $req = GET "/root/echo_arg?a=$encoded";
+ my ($res, $c) = ctx_request $req;
+
+ is $c->req->query_parameters->{'a'}, $shiftjs, 'got expected value';
+}
+
## should we use binmode on filehandles to force the encoding...?
## Not sure what else to do with multipart here, if docs are enough...