Adding documentation, and a 202 Accepted status helper
[catagits/Catalyst-Action-REST.git] / lib / Catalyst / Action / REST.pm
1 #
2 # REST.pm
3 # Created by: Adam Jacob, Marchex, <adam@marchex.com>
4 # Created on: 10/12/2006 03:00:32 PM PDT
5 #
6 # $Id$
7
8 package Catalyst::Action::REST;
9
10 use strict;
11 use warnings;
12
13 use base 'Catalyst::Action';
14 use Class::Inspector;
15 use 5.8.1;
16
17 my 
18 $VERSION = '0.1';
19
20 =head1 NAME
21
22 Catalyst::Action::REST - Automated REST Method Dispatching
23
24 =head1 SYNOPSIS
25
26     sub foo :Local :ActionClass('REST') {}
27
28     sub foo_GET { 
29       ... do something for GET requests ...
30     }
31
32     sub foo_PUT { 
33       ... do somethign for PUT requests ...
34     }
35
36 =head1 DESCRIPTION
37
38 This Action handles doing automatic method dispatching for REST requests.  It
39 takes a normal Catalyst action, and changes the dispatch to append an
40 underscore and method name. 
41
42 For example, in the synopsis above, calling GET on "/foo" would result in
43 the foo_GET method being dispatched.
44
45 If a method is requested that is not implemented, this action will 
46 return a status 405 (Method Not Found).  It will populate the "Allow" header 
47 with the list of implemented request methods.
48
49 It is likely that you really want to look at L<Catalyst::Controller::REST>.
50
51 =head1 METHODS
52
53 =over 4
54
55 =item dispatch
56
57 This method overrides the default dispatch mechanism to the re-dispatching
58 mechanism described above.
59
60 =cut
61 sub dispatch {
62     my $self = shift;
63     my $c = shift;
64
65     my $controller = $self->class;
66     my $method     = $self->name . "_" . uc( $c->request->method );
67     if ( $controller->can($method) ) {
68         return $controller->$method($c, @{$c->req->args});
69     } else {
70         $self->_return_405($c);
71         return $c->execute( $self->class, $self, @{$c->req->args} );
72     }
73 }
74
75 sub _return_405 {
76     my ( $self, $c ) = @_;
77
78     my $controller = $self->class;
79     my $methods    = Class::Inspector->methods($controller);
80     my @allowed;
81     foreach my $method ( @{$methods} ) {
82         my $name = $self->name;
83         if ( $method =~ /^$name\_(.+)$/ ) {
84             push( @allowed, $1 );
85         }
86     }
87     $c->response->content_type('text/plain');
88     $c->response->status(405);
89     $c->response->header( 'Allow' => \@allowed );
90     $c->response->body( "Method "
91           . $c->request->method
92           . " not implemented for "
93           . $c->uri_for( $self->reverse ) );
94 }
95
96 1;
97
98 =back
99
100 =head1 SEE ALSO
101
102 You likely want to look at L<Catalyst::Controller::REST>, which implements
103 a sensible set of defaults for a controller doing REST.
104
105 L<Catalyst::Action::Serialize>, L<Catalyst::Action::Deserialize>
106
107 =head1 AUTHOR
108
109 Adam Jacob <adam@stalecoffee.org>, with lots of help from mst and jrockway
110
111 Marchex, Inc. paid me while I developed this module.  (http://www.marchex.com)
112
113 =head1 LICENSE
114
115 You may distribute this code under the same terms as Perl itself.
116
117 =cut