use Catalyst::Middleware::Stash;
use Plack::Util;
use Class::Load 'load_class';
-use Encode 2.21 'encode_utf8';
+use Encode 2.21 'decode_utf8', 'encode_utf8';
BEGIN { require 5.008003; }
# Oh my, I wonder what filehandle responses and streams do... - jnap.
# Encode expects plain scalars (IV, NV or PV) and segfaults on ref's
- $c->response->body( $c->encoding->encode( $body, $c->_encode_check ) )
- if ref(\$body) eq 'SCALAR';
+ if (ref(\$body) eq 'SCALAR') {
+ $c->response->body( $c->encoding->encode( $body, $c->_encode_check ) );
+ };
}
=head2 $c->finalize_output
$method ||= '';
$path = '/' unless length $path;
$address ||= '';
+
+ $path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+ $path = decode_utf8($path);
+
$c->log->debug(qq/"$method" request for "$path" from "$address"/);
$c->log_request_headers($request->headers);
return unless $enc;
# Uggg we hook prepare uploads to do the encoding crap on post and query
- # parameters! Sorry -jnap
+ # parameters! Cargo culted from old encoding plugin. Sorry -jnap
for my $key (qw/ parameters query_parameters body_parameters /) {
for my $value ( values %{ $c->request->{$key} } ) {
# N.B. Check if already a character string and if so do not try to double decode.
use Catalyst::Utils;
use URI;
use Scalar::Util ();
+use Encode 2.21 'decode_utf8';
has _endpoints => (
is => 'rw',
push(@rows, [ '', $name ]);
}
push(@rows, [ '', (@rows ? "=> " : '').($extra ? "$extra " : '')."/${endpoint}". ($consumes ? " :$consumes":"" ) ]);
- $rows[0][0] = join('/', '', @parts) || '/';
+ my @display_parts = map { $_ =~s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; decode_utf8 $_ } @parts;
+ $rows[0][0] = join('/', '', @display_parts) || '/';
$paths->row(@$_) for @rows;
}
);
}
- $action->attributes->{PathPart} = [ $part ];
+ my $encoded_part = URI->new($part)->canonical;
+ $encoded_part =~ s{(?<=[^/])/+\z}{};
- unshift(@{ $children->{$part} ||= [] }, $action);
+ $action->attributes->{PathPart} = [ $encoded_part ];
+
+ unshift(@{ $children->{$encoded_part} ||= [] }, $action);
$self->_actions->{'/'.$action->reverse} = $action;
use Text::SimpleTable;
use Catalyst::Utils;
use URI;
+use Encode 2.21 'decode_utf8';
has _paths => (
is => 'rw',
my $display_path = "/$path/$parts";
$display_path =~ s{/{1,}}{/}g;
-
+ $display_path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; # deconvert urlencoded for pretty view
+ $display_path = decode_utf8 $display_path; # URI does encoding
$paths->row( $display_path, "/$action" );
}
}
use Tree::Simple;
use Tree::Simple::Visitor::FindByPath;
use Class::Load qw(load_class try_load_class);
+use Encode 2.21 'decode_utf8';
use namespace::clean -except => 'meta';
}
else {
my $path = $c->req->path;
+ $path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+ $path = decode_utf8($path);
+
my $error = $path
? qq/Unknown resource "$path"/
: "No default action defined";
s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg for grep { defined } @{$req->captures||[]};
- $c->log->debug( 'Path is "' . $req->match . '"' )
- if ( $c->debug && defined $req->match && length $req->match );
+ if($c->debug && defined $req->match && length $req->match) {
+ my $match = $req->match;
+ $match =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+ $match = decode_utf8($match);
+ $c->log->debug( 'Path is "' . $match . '"' )
+ }
- $c->log->debug( 'Arguments are "' . join( '/', @args ) . '"' )
+ $c->log->debug( 'Arguments are "' . join( '/', map { decode_utf8 $_ } @args ) . '"' )
if ( $c->debug && @args );
}
if ($self->can('_has_psgi_errors') and $self->_has_psgi_errors) {
$self->_psgi_errors->print(@_);
} else {
+ binmode STDERR, ":utf8";
print STDERR @_;
}
}
--- /dev/null
+use utf8;
+use warnings;
+use strict;
+use Test::More;
+
+# Test cases for incoming utf8
+
+{
+ package MyApp::Controller::Root;
+ $INC{'MyApp/Controller/Root.pm'} = __FILE__;
+
+ use base 'Catalyst::Controller';
+
+ sub heart :Path('♥') {
+ my ($self, $c) = @_;
+ $c->response->content_type('text/html');
+ $c->response->body("<p>This is path-heart action ♥</p>");
+ # We let the content length middleware find the length...
+ }
+
+ sub hat :Path('^') {
+ my ($self, $c) = @_;
+ $c->response->content_type('text/html');
+ $c->response->body("<p>This is path-hat action ^</p>");
+ }
+
+ sub base :Chained('/') CaptureArgs(0) { }
+ sub link :Chained('base') PathPart('♥') Args(0) {
+ my ($self, $c) = @_;
+ $c->response->content_type('text/html');
+ $c->response->body("<p>This is base-link action ♥</p>");
+ }
+
+ package MyApp;
+ use Catalyst;
+
+ MyApp->config(encoding=>'UTF-8');
+
+ Test::More::ok(MyApp->setup, 'setup app');
+}
+
+ok my $psgi = MyApp->psgi_app, 'build psgi app';
+
+use Catalyst::Test 'MyApp';
+use Encode 2.21 'decode_utf8';
+
+{
+ my $res = request "/root/♥";
+
+ is $res->code, 200, 'OK';
+ is decode_utf8($res->content), '<p>This is path-heart action ♥</p>', 'correct body';
+ is $res->content_length, 36, 'correct length';
+}
+
+{
+ my $res = request "/root/^";
+
+ is $res->code, 200, 'OK';
+ is decode_utf8($res->content), '<p>This is path-hat action ^</p>', 'correct body';
+ is $res->content_length, 32, 'correct length';
+}
+
+{
+ my $res = request "/base/♥";
+
+ is $res->code, 200, 'OK';
+ is decode_utf8($res->content), '<p>This is base-link action ♥</p>', 'correct body';
+ is $res->content_length, 35, 'correct length';
+}
+
+{
+ my $res = request "/base/♥?♥=♥♥";
+
+ is $res->code, 200, 'OK';
+ is decode_utf8($res->content), '<p>This is base-link action ♥</p>', 'correct body';
+ is $res->content_length, 35, 'correct length';
+}
+
+
+done_testing;