create status 302 "found"
[catagits/Catalyst-Action-Serialize-Data-Serializer.git] / lib / Catalyst / Controller / REST.pm
index 3bd6daa..92c7b0d 100644 (file)
@@ -2,7 +2,7 @@ package Catalyst::Controller::REST;
 use Moose;
 use namespace::autoclean;
 
-our $VERSION = '0.91';
+our $VERSION = '0.93';
 $VERSION = eval $VERSION;
 
 =head1 NAME
@@ -234,6 +234,25 @@ Your views should have a C<process> method like this:
       return $serialized;
   }
 
+=item * Callback
+
+For infinite flexibility, you can provide a callback for the
+deserialization/serialization steps.
+
+  __PACKAGE__->config(
+      map => {
+          'text/xml'  => [ 'Callback', { deserialize => \&parse_xml, serialize => \&render_xml } ],
+      }
+  );
+
+The C<deserialize> callback is passed a string that is the body of the
+request and is expected to return a scalar value that results from
+the deserialization.  The C<serialize> callback is passed the data
+structure that needs to be serialized and must return a string suitable
+for returning in the HTTP response.  In addition to receiving the scalar
+to act on, both callbacks are passed the controller object and the context
+(i.e. C<$c>) as the second and third arguments.
+
 =back
 
 By default, L<Catalyst::Controller::REST> will return a 
@@ -436,6 +455,36 @@ sub status_multiple_choices {
     return 1;
 }
 
+=item status_found
+
+Returns a "302 FOUND" response. Takes an "entity" to serialize.
+Also takes optional "location" for preferred choice.
+
+=cut
+
+sub status_found {
+    my $self = shift;
+    my $c    = shift;
+    my %p    = Params::Validate::validate(
+        @_,
+        {
+            entity => 1,
+            location => { type     => SCALAR | OBJECT, optional => 1 },
+        },
+    );
+
+    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'};
+    $self->_set_entity( $c, $p{'entity'} );
+    return 1;
+}
+
 =item status_bad_request
 
 Returns a "400 BAD REQUEST" response.  Takes a "message" argument
@@ -462,6 +511,32 @@ sub status_bad_request {
     return 1;
 }
 
+=item status_forbidden
+
+Returns a "403 FORBIDDEN" response.  Takes a "message" argument
+as a scalar, which will become the value of "error" in the serialized
+response.
+
+Example:
+
+  $self->status_forbidden(
+    $c,
+    message => "access denied",
+  );
+
+=cut
+
+sub status_forbidden {
+    my $self = shift;
+    my $c    = shift;
+    my %p    = Params::Validate::validate( @_, { message => { type => SCALAR }, }, );
+
+    $c->response->status(403);
+    $c->log->debug( "Status Forbidden: " . $p{'message'} ) if $c->debug;
+    $self->_set_entity( $c, { error => $p{'message'} } );
+    return 1;
+}
+
 =item status_not_found
 
 Returns a "404 NOT FOUND" response.  Takes a "message" argument
@@ -594,6 +669,10 @@ action classes:
 
   sub serialize : ActionClass('Serialize') {}
 
+If you need to deserialize multipart requests (i.e. REST data in
+one part and file uploads in others) you can do so by using the
+L<Catalyst::Action::DeserializeMultiPart> action class.
+
 =back
 
 =head1 A MILD WARNING