new action method "list_extra_info" for better debugging, and did this for the new...
[catagits/Catalyst-Runtime.git] / lib / Catalyst / ActionRole / HTTPMethods.pm
1 package Catalyst::ActionRole::HTTPMethods;
2
3 use Moose::Role;
4
5 requires 'match', 'match_captures', 'list_extra_info';
6
7 around ['match','match_captures'], sub {
8   my ($orig, $self, $ctx, @args) = @_;
9   my $expected = $self->_normalize_expected_http_method($ctx->req);
10   return $self->_has_expected_http_method($expected) ?
11     $self->$orig($ctx, @args) :
12     0;
13 };
14
15 sub _normalize_expected_http_method {
16   my ($self, $req) = @_;
17   return $req->header('X-HTTP-Method') ||
18     $req->header('X-HTTP-Method-Override') ||
19     $req->header('X-METHOD-OVERRIDE') ||
20     $req->method;
21 }
22
23 sub _has_expected_http_method {
24   my ($self, $expected) = @_;
25   return 1 unless scalar(my @allowed = $self->allowed_http_methods);
26   return scalar(grep { lc($_) eq lc($expected) } @allowed) ?
27     1 : 0;
28 }
29
30 sub allowed_http_methods { @{shift->attributes->{Method}||[]} }
31
32 sub list_extra_info { sort shift->allowed_http_methods }
33
34 1;
35
36 =head1 NAME
37
38 Catalyst::ActionRole::HTTPMethods - Match on HTTP Methods
39
40 =head1 SYNOPSIS
41
42     package MyApp::Web::Controller::MyController;
43
44     use Moose;
45     use MooseX::MethodAttributes;
46
47     extends 'Catalyst::Controller';
48
49     sub user_base : Chained('/') CaptureArg(0) { ... }
50
51       sub get_user    : Chained('user_base') Args(1) GET { ... }
52       sub post_user   : Chained('user_base') Args(1) POST { ... }
53       sub put_user    : Chained('user_base') Args(1) PUT { ... }
54       sub delete_user : Chained('user_base') Args(1) DELETE { ... }
55       sub head_user   : Chained('user_base') Args(1) HEAD { ... }
56       sub option_user : Chained('user_base') Args(1) OPTION { ... }
57       sub option_user : Chained('user_base') Args(1) PATCH { ... }
58
59
60       sub post_and_put : Chained('user_base') POST PUT Args(1) { ... }
61       sub method_attr  : Chained('user_base') Method('DELETE') Args(0) { ... }
62
63     __PACKAGE__->meta->make_immutable;
64
65 =head1 DESCRIPTION
66
67 This is an action role that lets your L<Catalyst::Action> match on standard
68 HTTP methods, such as GET, POST, etc.
69
70 Since most web browsers have limited support for rich HTTP Method vocabularies
71 we also support setting the expected match method via the follow non standard
72 but widely used http extensions.  Our support for these should not be taken as
73 an endorsement of the technique.   Rt is merely a reflection of our desire to
74 work well with existing systems and common client side tools.
75
76 =over 4
77
78 =item X-HTTP-Method (Microsoft)
79
80 =item X-HTTP-Method-Override (Google/GData)
81
82 =item X-METHOD-OVERRIDE (IBM)
83
84 =back 
85
86 Please note the insanity of overriding a GET request with a DELETE override...
87 Rational practices suggest that using POST with overrides to emulate PUT and
88 DELETE can be an acceptable way to deal with client limitations and security
89 rules on your proxy server. I recommend going no further.
90
91 =head1 REQUIRES
92
93 This role requires the following methods in the consuming class.
94
95 =head2 match
96
97 =head2 match_captures
98
99 Returns 1 if the action matches the existing request and zero if not.
100
101 =head1 METHODS
102
103 This role defines the following methods
104
105 =head2 match
106
107 =head2 match_captures
108
109 Around method modifier that return 1 if the request method matches one of the
110 allowed methods (see L</http_methods>) and zero otherwise.
111
112 =head2 allowed_http_methods
113
114 An array of strings that are the allowed http methods for matching this action
115 normalized as noted above (using X-Method* overrides).
116
117 =head2 list_extra_info
118
119 Returns an array of the allowed HTTP Methods, sorted.
120
121 =head2 _has_expected_http_method ($expected)
122
123 Private method which returns 1 if C<$expected> matches one of the allowed
124 in L</http_methods> and zero otherwise.
125
126 =head1 AUTHORS
127
128 Catalyst Contributors, see Catalyst.pm
129
130 =head1 COPYRIGHT
131
132 This library is free software. You can redistribute it and/or modify it under
133 the same terms as Perl itself.
134
135 =cut