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