Skip Menu |

This queue is for tickets about the Catalyst-Action-REST CPAN distribution.

Report information
The Basics
Id: 27949
Status: resolved
Priority: 0/
Queue: Catalyst-Action-REST

People
Owner: holoway [...] cpan.org
Requestors: dmo+pause [...] dmo.ca
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 0.41
Fixed in: (no value)



Subject: Content-type: header set incorrectly when default handler used
Catalyst::Action::REST will occasionally return content with incorrect content types. The scenario: - You have {serialize}->{default} = 'YAML' (or whatever) configured in your app - A request comes in with "Accept: */*" What happens internally: - $c->request->preferred_content_type gets set to "*/*" - no handler is found for */*, so we fall back to default (in _load_content_plugins) but leave the content type as we found it. - we happily serialize with the default handler, and return a response with a header of "Content-type: */*" To fix this, we need some way of knowing what the MIME type of the data returned by the default serializer might be. The easiest way I see of doing this would be to have the 'default' config option be a MIME type that would then be looked up in {serialize}->{map} instead of the basename of a serializer class. Then, we've got both bits of information at the same time, and can set $sclass and $content_type appropriately in _load_content_plugins().
Thanks. I'll look into this. I would also happily accept a patch, if you're feeling like whipping one up. Regards, Adam
On Tue Jul 03 20:50:50 2007, HOLOWAY wrote: Show quoted text
> Thanks. I'll look into this. I would also happily accept a patch, if > you're feeling like whipping one up.
Ok, patch attached.
From 2ad273f58cdd387ee23b09d03a7f42ada8e0d563 Mon Sep 17 00:00:00 2001 From: Dave O'Neill <dmo@roaringpenguin.com> Date: Wed, 4 Jul 2007 11:25:00 -0400 Subject: [PATCH] Correctly set Content-type: header when using default serializer. This changes the {serialize}->{default} config setting to take the name of a valid content-type defined in {serialize}->{map}, rather than a plugin name. This gives us enough information to set the Content-type: header appropriately when serializing. Fixes rt.cpan.org 27949 --- Changelog | 17 +++++++++++------ README | 5 +++-- lib/Catalyst/Action/Deserialize.pm | 2 +- lib/Catalyst/Action/Serialize.pm | 11 ++++++----- lib/Catalyst/Action/SerializeBase.pm | 17 ++++++++++++----- lib/Catalyst/Controller/REST.pm | 11 ++++++----- t/catalyst-action-serialize-accept.t | 31 ++++++++++++++++++++++++------- 7 files changed, 63 insertions(+), 31 deletions(-) diff --git a/Changelog b/Changelog index 3997004..5255c63 100644 --- a/Changelog +++ b/Changelog @@ -1,12 +1,17 @@ +Wed Jul 04 11:17:20 EDT 2007 + Fixed 'default' serializer to set a valid Content-Type: header. Fixes + RT ticket 27949. Note that behavior has changed -- the default + serializer must now be specified as a content-type, not as a plugin + name. (dmo@roaringpenguin.com) + Thu May 24 14:01:06 PDT 2007 (adam) - Release 0.41 - Moved a bogus $self->class to $c->component($self->class) + Moved a bogus $self->class to $c->component($self->class) Fri Mar 9 14:13:29 PST 2007 (adam) - Release 0.40 - Refactored the Content-Type negotiation to live in Catalyst::Request::REST. - (drolsky) - Added some useful debugging. (drolsky) - Added a View serializer/deserializer, which simply calls the correct - Catalyst view. ('text/html' => [ 'View', 'TT' ]) (claco, adam) + Refactored the Content-Type negotiation to live in Catalyst::Request::REST. (drolsky) + Added some useful debugging. (drolsky) + Added a View serializer/deserializer, which simply calls the correct + Catalyst view. ('text/html' => [ 'View', 'TT' ]) (claco, adam) Wed Dec 6 00:45:02 PST 2006 (adam) - Release 0.31 Fixed a bug where we would report a blank content-type negotiation. diff --git a/README b/README index 8da598b..172ac8e 100644 --- a/README +++ b/README @@ -140,9 +140,10 @@ AVAILABLE SERIALIZERS made. You can ensure that something is always returned by setting the "default" config option: - __PACKAGE__->config->{'serialize'}->{'default'} = 'YAML'; + __PACKAGE__->config->{'serialize'}->{'default'} = 'text/x-yaml'; - Would make it always fall back to YAML. + Would make it always fall back to the serializer plugin defined for + text/x-yaml. Implementing new Serialization formats is easy! Contributions are most welcome! See Catalyst::Action::Serialize and diff --git a/lib/Catalyst/Action/Deserialize.pm b/lib/Catalyst/Action/Deserialize.pm index c45d86b..f89447f 100644 --- a/lib/Catalyst/Action/Deserialize.pm +++ b/lib/Catalyst/Action/Deserialize.pm @@ -53,7 +53,7 @@ Catalyst::Action::Deserialize - Deserialize Data in a Request __PACKAGE__->config( serialize => { - 'default' => 'YAML', + 'default' => 'text/x-yaml', 'stash_key' => 'rest', 'map' => { 'text/x-yaml' => 'YAML', diff --git a/lib/Catalyst/Action/Serialize.pm b/lib/Catalyst/Action/Serialize.pm index 2ec7add..a55d531 100644 --- a/lib/Catalyst/Action/Serialize.pm +++ b/lib/Catalyst/Action/Serialize.pm @@ -66,10 +66,10 @@ Catalyst::Action::Serialize - Serialize Data in a Response __PACKAGE__->config( serialize => { - 'default' => 'YAML', + 'default' => 'text/x-yaml', 'stash_key' => 'rest', 'map' => { - 'text/html' => [ 'View', 'TT', ], + 'text/html' => [ 'View', 'TT', ], 'text/x-yaml' => 'YAML', 'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ], }, @@ -106,9 +106,10 @@ L<Catalyst::Request::REST>. =item default -The default Serialization format. See the next section for -available options. This is used if a requested content-type -is not recognized. +The Content-Type of the default Serialization format. This must be a +Content-Type associated with a plugin in the "map" section below. + +This is used if a requested content-type is not recognized. =item stash_key diff --git a/lib/Catalyst/Action/SerializeBase.pm b/lib/Catalyst/Action/SerializeBase.pm index 2d15713..546f49a 100644 --- a/lib/Catalyst/Action/SerializeBase.pm +++ b/lib/Catalyst/Action/SerializeBase.pm @@ -44,6 +44,17 @@ sub _load_content_plugins { my $sclass = $search_path . "::"; my $sarg; my $map = $controller->config->{'serialize'}->{'map'}; + + # If we don't have a handler for our preferred content type, try + # the default + if ( ! exists $map->{$content_type} ) { + if( exists $controller->config->{'serialize'}->{'default'} ) { + $content_type = $controller->config->{'serialize'}->{'default'} ; + } else { + return $self->_unsupported_media_type($c, $content_type); + } + } + if ( exists( $map->{$content_type} ) ) { my $mc; if ( ref( $map->{$content_type} ) eq "ARRAY" ) { @@ -64,11 +75,7 @@ sub _load_content_plugins { return $self->_unsupported_media_type($c, $content_type); } } else { - if ( exists( $controller->config->{'serialize'}->{'default'} ) ) { - $sclass .= $controller->config->{'serialize'}->{'default'}; - } else { - return $self->_unsupported_media_type($c, $content_type); - } + return $self->_unsupported_media_type($c, $content_type); } unless ( exists( $self->_loaded_plugins->{$sclass} ) ) { my $load_class = $sclass; diff --git a/lib/Catalyst/Controller/REST.pm b/lib/Catalyst/Controller/REST.pm index 9547326..3761f07 100644 --- a/lib/Catalyst/Controller/REST.pm +++ b/lib/Catalyst/Controller/REST.pm @@ -170,13 +170,14 @@ Will do the trick nicely. =back -By default, L<Catalyst::Controller::REST> will return a C<415 Unsupported Media Type> response if an attempt to use an unsupported content-type is made. You -can ensure that something is always returned by setting the C<default> config -option: +By default, L<Catalyst::Controller::REST> will return a C<415 Unsupported Media Type> +response if an attempt to use an unsupported content-type is made. You +can ensure that something is always returned by setting the C<default> +config option: - __PACKAGE__->config->{'serialize'}->{'default'} = 'YAML'; + __PACKAGE__->config->{'serialize'}->{'default'} = 'text/x-yaml'; -Would make it always fall back to YAML. +Would make it always fall back to the serializer plugin defined for text/x-yaml. Implementing new Serialization formats is easy! Contributions are most welcome! See L<Catalyst::Action::Serialize> and diff --git a/t/catalyst-action-serialize-accept.t b/t/catalyst-action-serialize-accept.t index b67062e..e91c27e 100644 --- a/t/catalyst-action-serialize-accept.t +++ b/t/catalyst-action-serialize-accept.t @@ -14,6 +14,7 @@ use Catalyst; __PACKAGE__->config( name => 'Test::Catalyst::Action::Serialize', serialize => { + 'default' => 'text/x-yaml', 'stash_key' => 'rest', 'map' => { 'text/x-yaml' => 'YAML', @@ -43,7 +44,7 @@ package main; use strict; use warnings; -use Test::More tests => 3; +use Test::More tests => 7; use Data::Serializer; use FindBin; use Data::Dump qw(dump); @@ -56,15 +57,31 @@ my $t = Test::Rest->new('content_type' => 'text/x-yaml'); use_ok 'Catalyst::Test', 'Test::Catalyst::Action::Serialize'; -my $req = $t->get(url => '/test'); -$req->remove_header('Content-Type'); -$req->header('Accept', 'text/x-yaml'); -my $res = request($req); -ok( $res->is_success, 'GET the serialized request succeeded' ); my $data = <<EOH; --- lou: is my cat EOH -is( $res->content, $data, "Request returned proper data"); + +{ + my $req = $t->get(url => '/test'); + $req->remove_header('Content-Type'); + $req->header('Accept', 'text/x-yaml'); + my $res = request($req); + ok( $res->is_success, 'GET the serialized request succeeded' ); + is( $res->content, $data, "Request returned proper data"); + is( $res->header('Content-type'), 'text/x-yaml', '... with expected content-type') +} + +# Make sure we don't get a bogus content-type when using default +# serializer (rt.cpan.org ticket 27949) +{ + my $req = $t->get(url => '/test'); + $req->remove_header('Content-Type'); + $req->header('Accept', '*/*'); + my $res = request($req); + ok( $res->is_success, 'GET the serialized request succeeded' ); + is( $res->content, $data, "Request returned proper data"); + is( $res->header('Content-type'), 'text/x-yaml', '... with expected content-type') +} 1; -- 1.5.2.2.239.g89630
From: HOLOWAY [...] cpan.org
Thanks. This has been applied, and released to CPAN as Catalyst::Action::REST 0.50. Well done! On Wed Jul 04 11:36:24 2007, DONEILL wrote: Show quoted text
> On Tue Jul 03 20:50:50 2007, HOLOWAY wrote:
> > Thanks. I'll look into this. I would also happily accept a patch, if > > you're feeling like whipping one up.
> > Ok, patch attached.
Patch applied to the repository, released as Catalyst::Action::REST 0.50.