# 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..
# 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;
Hook to let you customize how encoding errors are handled. By default
we just throw an exception. Receives a hashref of debug information.
-Example:
+Example of call:
$c->handle_unicode_encoding_exception({
param_value => $value,
error_msg => $_,
- encoding_step => 'params',
+ encoding_step => 'params',
});
+You can override this for custom handling of unicode errors. If you want a
+custom response here, one approach is to throw an HTTP style 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 1;
+ }
+
=cut
sub handle_unicode_encoding_exception {
--- /dev/null
+use strict;
+use warnings;
+use Test::More;
+
+BEGIN {
+ package TestApp::Exception;
+ $INC{'TestApp/Exception.pm'} = __FILE__;
+
+ sub new {
+ my ($class, $code, $headers, $body) = @_;
+ return bless +{res => [$code, $headers, $body]}, $class;
+ }
+
+ sub throw { die shift->new(@_) }
+
+ sub as_psgi {
+ my ($self, $env) = @_;
+ my ($code, $headers, $body) = @{$self->{res}};
+
+ return [$code, $headers, $body]; # for now
+
+ return sub {
+ my $responder = shift;
+ $responder->([$code, $headers, $body]);
+ };
+ }
+
+ package TestApp::Controller::Root;
+ $INC{'TestApp/Controller/Root.pm'} = __FILE__;
+
+ use Moose;
+ use MooseX::MethodAttributes;
+ extends 'Catalyst::Controller';
+
+ sub main :Path('') :Args(1) {
+ my ($self, $c, $arg) = @_;
+ $c->res->body('<h1>OK</h1>');
+ $c->res->content_type('text/html');
+ }
+
+ TestApp::Controller::Root->config(namespace => '');
+}
+
+{
+ package TestApp;
+ $INC{'TestApp.pm'} = __FILE__;
+
+ use Catalyst;
+ use TestApp::Exception;
+
+ sub handle_unicode_encoding_exception {
+ my ( $self, $param_value, $error_msg ) = @_;
+ TestApp::Exception->throw(
+ 200, ['content-type'=>'text/plain'], ['Bad unicode data']);
+ }
+
+ __PACKAGE__->setup;
+}
+
+
+use Catalyst::Test 'TestApp';
+
+{
+ my $res = request('/ok');
+ is ($res->status_line, "200 OK");
+ is ($res->content, '<h1>OK</h1>');
+}
+
+{
+ my $res = request('/%E2%C3%83%C6%92%C3%8');
+ is ($res->content, 'Bad unicode data');
+}
+
+done_testing;
+
+#TestApp->to_app;