__PACKAGE__->_encode_check(Encode::FB_CROAK | Encode::LEAVE_SRC);
# Remember to update this in Catalyst::Runtime as well!
-our $VERSION = '5.90084';
+our $VERSION = '5.90089_001';
$VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
sub import {
however if your targeted action or action chain has the Scheme attribute it will
use that instead.
+Also, if the targeted Action or Action chain declares Args/CaptureArgs that have
+type constraints, we will require that your proposed URL verify on those declared
+constraints.
+
=cut
sub uri_for {
carp "uri_for called with undef argument" if grep { ! defined $_ } @args;
- my @encoded_args = ();
- foreach my $arg (@args) {
- if(ref($arg)||'' eq 'ARRAY') {
- push @encoded_args, [map {
- my $encoded = encode_utf8 $_;
- $encoded =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
- $encoded;
- } @$arg];
- } else {
- push @encoded_args, do {
- my $encoded = encode_utf8 $arg;
- $encoded =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
- $encoded;
- }
- }
- }
-
my $target_action = $path->$_isa('Catalyst::Action') ? $path : undef;
if ( $path->$_isa('Catalyst::Action') ) { # action object
- s|/|%2F|g for @encoded_args;
+ s|/|%2F|g for @args;
my $captures = [ map { s|/|%2F|g; $_; }
- ( scalar @encoded_args && ref $encoded_args[0] eq 'ARRAY'
- ? @{ shift(@encoded_args) }
+ ( scalar @args && ref $args[0] eq 'ARRAY'
+ ? @{ shift(@args) }
: ()) ];
my $action = $path;
+ my $expanded_action = $c->dispatcher->expand_action( $action );
+ my $num_captures = $expanded_action->number_of_captures;
+
# ->uri_for( $action, \@captures_and_args, \%query_values? )
- if( !@encoded_args && $action->number_of_args ) {
- my $expanded_action = $c->dispatcher->expand_action( $action );
- my $num_captures = $expanded_action->number_of_captures;
- unshift @encoded_args, splice @$captures, $num_captures;
+ if( !@args && $action->number_of_args ) {
+ unshift @args, splice @$captures, $num_captures;
}
- $path = $c->dispatcher->uri_for_action($action, $captures);
+ if($num_captures) {
+ unless($expanded_action->match_captures($c, $captures)) {
+ carp "captures [@{$captures}] do not match the type constraints in actionchain ending with '$action'";
+ return;
+ }
+ }
+
+ $path = $c->dispatcher->uri_for_action($action, $captures);
if (not defined $path) {
$c->log->debug(qq/Can't find uri_for action '$action' @$captures/)
if $c->debug;
return undef;
}
$path = '/' if $path eq '';
+
+ # 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;
+ }
+ }
}
- unshift(@encoded_args, $path);
+ unshift(@args, $path);
unless (defined $path && $path =~ s!^/!!) { # in-place strip
my $namespace = $c->namespace;
if (defined $path) { # cheesy hack to handle path '../foo'
- $namespace =~ s{(?:^|/)[^/]+$}{} while $encoded_args[0] =~ s{^\.\./}{};
+ $namespace =~ s{(?:^|/)[^/]+$}{} while $args[0] =~ s{^\.\./}{};
}
- unshift(@encoded_args, $namespace || '');
+ unshift(@args, $namespace || '');
}
# join args with '/', or a blank string
- my $args = join('/', grep { defined($_) } @encoded_args);
+ my $args = join('/', grep { defined($_) } @args);
$args =~ s/\?/%3F/g; # STUPID STUPID SPECIAL CASE
$args =~ s!^/+!!;
} @keys);
}
+ $base = encode_utf8 $base;
+ $base =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+ $args = encode_utf8 $args;
+ $args =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+
my $res = bless(\"${base}${args}${query}", $class);
$res;
}
=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
+AND all those matching actions declared Args(0), we'd break the tie by choosing
+the first action defined. We now normalized how Args(0) works so that it
+follows the same rule as Args(N), which is to say when we need to break a tie
+we choose the LAST action defined. If this breaks your code and you don't
+have time to update to follow the new normalized approach, you may set this
+value to true and it will globally revert to the original chaining behavior.
+
+=item *
+
C<psgi_middleware> - See L<PSGI MIDDLEWARE>.
=item *