X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FController%2FREST.pm;h=3c9ec67cd2caa390895b0937b872d6b5f539c238;hb=c0008fc76f34cc22ceaf80003191f73a2300bfe5;hp=92c7b0da134b78ab6b590aaff178bf531a83e238;hpb=e52456a4e301e6443284318748eb328641d8737a;p=catagits%2FCatalyst-Action-REST.git diff --git a/lib/Catalyst/Controller/REST.pm b/lib/Catalyst/Controller/REST.pm index 92c7b0d..3c9ec67 100644 --- a/lib/Catalyst/Controller/REST.pm +++ b/lib/Catalyst/Controller/REST.pm @@ -1,10 +1,8 @@ package Catalyst::Controller::REST; + use Moose; use namespace::autoclean; -our $VERSION = '0.93'; -$VERSION = eval $VERSION; - =head1 NAME Catalyst::Controller::REST - A RESTful controller @@ -14,7 +12,7 @@ Catalyst::Controller::REST - A RESTful controller package Foo::Controller::Bar; use Moose; use namespace::autoclean; - + BEGIN { extends 'Catalyst::Controller::REST' } sub thing : Local : ActionClass('REST') { } @@ -39,15 +37,15 @@ Catalyst::Controller::REST - A RESTful controller my ( $self, $c ) = @_; $radiohead = $c->req->data->{radiohead}; - + $self->status_created( $c, - location => $c->req->uri->as_string, + location => $c->req->uri, entity => { radiohead => $radiohead, } ); - } + } =head1 DESCRIPTION @@ -81,7 +79,7 @@ which are described below. "The HTTP POST, PUT, and OPTIONS methods will all automatically L the contents of -C<< $c->request->body >> into the C<< $c->request->data >> hashref", based on +C<< $c->request->body >> into the C<< $c->request->data >> hashref", based on the request's C header. A list of understood serialization formats is L. @@ -175,14 +173,6 @@ Uses the L module to generate L output. Uses the L module to generate L output. -=item * C => C - -Uses the L module to generate L output. - -=item * C => C - -Uses the L module to generate L output. - =item * C => C Uses the L module to generate L output. @@ -225,7 +215,7 @@ Your views should have a C method like this: $c->response->body( $output ); return 1; # important } - + sub serialize { my ( $self, $data ) = @_; @@ -255,7 +245,7 @@ to act on, both callbacks are passed the controller object and the context =back -By default, L will return a +By default, L 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 config option: @@ -268,12 +258,12 @@ C. =head1 CUSTOM SERIALIZERS Implementing new Serialization formats is easy! Contributions -are most welcome! If you would like to implement a custom serializer, +are most welcome! If you would like to implement a custom serializer, you should create two new modules in the L and L namespace. Then assign your new class to the content-type's you want, and you're done. -See L and L +See L and L for more information. =head1 STATUS HELPERS @@ -299,19 +289,11 @@ __PACKAGE__->mk_accessors(qw(serialize)); __PACKAGE__->config( 'stash_key' => 'rest', 'map' => { - 'text/html' => 'YAML::HTML', 'text/xml' => 'XML::Simple', - 'text/x-yaml' => 'YAML', 'application/json' => 'JSON', 'text/x-json' => 'JSON', - 'text/x-data-dumper' => [ 'Data::Serializer', 'Data::Dumper' ], - 'text/x-data-denter' => [ 'Data::Serializer', 'Data::Denter' ], - 'text/x-data-taxi' => [ 'Data::Serializer', 'Data::Taxi' ], - 'application/x-storable' => [ 'Data::Serializer', 'Storable' ], - 'application/x-freezethaw' => [ 'Data::Serializer', 'FreezeThaw' ], - 'text/x-config-general' => [ 'Data::Serializer', 'Config::General' ], - 'text/x-php-serialization' => [ 'Data::Serializer', 'PHP::Serialization' ], }, + 'compliance_mode' => 0, ); sub begin : ActionClass('Deserialize') { } @@ -352,7 +334,7 @@ Example: $self->status_created( $c, - location => $c->req->uri->as_string, + location => $c->req->uri, entity => { radiohead => "Is a good band!", } @@ -374,14 +356,8 @@ sub status_created { }, ); - my $location; - if ( ref( $p{'location'} ) ) { - $location = $p{'location'}->as_string; - } else { - $location = $p{'location'}; - } $c->response->status(201); - $c->response->header( 'Location' => $location ); + $c->response->header( 'Location' => $p{location} ); $self->_set_entity( $c, $p{'entity'} ); return 1; } @@ -389,11 +365,13 @@ sub status_created { =item status_accepted Returns a "202 ACCEPTED" response. Takes an "entity" to serialize. +Also takes optional "location" for queue type scenarios. Example: $self->status_accepted( $c, + location => $c->req->uri, entity => { status => "queued", } @@ -404,9 +382,16 @@ Example: sub status_accepted { my $self = shift; my $c = shift; - my %p = Params::Validate::validate( @_, { entity => 1, }, ); + my %p = Params::Validate::validate( + @_, + { + location => { type => SCALAR | OBJECT, optional => 1 }, + entity => 1, + }, + ); $c->response->status(202); + $c->response->header( 'Location' => $p{location} ) if exists $p{location}; $self->_set_entity( $c, $p{'entity'} ); return 1; } @@ -443,14 +428,8 @@ sub status_multiple_choices { }, ); - my $location; - if ( ref( $p{'location'} ) ) { - $location = $p{'location'}->as_string; - } else { - $location = $p{'location'}; - } $c->response->status(300); - $c->response->header( 'Location' => $location ) if exists $p{'location'}; + $c->response->header( 'Location' => $p{location} ) if exists $p{'location'}; $self->_set_entity( $c, $p{'entity'} ); return 1; } @@ -458,7 +437,7 @@ sub status_multiple_choices { =item status_found Returns a "302 FOUND" response. Takes an "entity" to serialize. -Also takes optional "location" for preferred choice. +Also takes optional "location". =cut @@ -473,14 +452,8 @@ sub status_found { }, ); - my $location; - if ( ref( $p{'location'} ) ) { - $location = $p{'location'}->as_string; - } else { - $location = $p{'location'}; - } $c->response->status(302); - $c->response->header( 'Location' => $location ) if exists $p{'location'}; + $c->response->header( 'Location' => $p{location} ) if exists $p{'location'}; $self->_set_entity( $c, $p{'entity'} ); return 1; } @@ -588,6 +561,79 @@ sub status_gone { return 1; } +=item status_see_other + +Returns a "303 See Other" response. Takes an optional "entity" to serialize, +and a "location" where the client should redirect to. + +Example: + + $self->status_see_other( + $c, + location => $some_other_url, + entity => { + radiohead => "Is a good band!", + } + ); + +=cut + +sub status_see_other { + my $self = shift; + my $c = shift; + my %p = Params::Validate::validate( + @_, + { + location => { type => SCALAR | OBJECT }, + entity => { optional => 1 }, + }, + ); + + $c->response->status(303); + $c->response->header( 'Location' => $p{location} ); + $self->_set_entity( $c, $p{'entity'} ); + return 1; +} + +=item status_moved + +Returns a "301 MOVED" response. Takes an "entity" to serialize, and a +"location" where the created object can be found. + +Example: + + $self->status_moved( + $c, + location => '/somewhere/else', + entity => { + radiohead => "Is a good band!", + }, + ); + +=cut + +sub status_moved { + my $self = shift; + my $c = shift; + my %p = Params::Validate::validate( + @_, + { + location => { type => SCALAR | OBJECT }, + entity => { optional => 1 }, + }, + ); + + my $location = ref $p{location} + ? $p{location}->as_string + : $p{location} + ; + + $c->response->status(301); + $c->response->header( Location => $location ); + $self->_set_entity($c, $p{entity}); + return 1; +} + sub _set_entity { my $self = shift; my $c = shift;