update distar url
[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 sub allowed_http_methods { @{shift->attributes->{Method}||[]} }
8
9 sub _has_expected_http_method {
10   my ($self, $expected) = @_;
11   return 1 unless scalar(my @allowed = $self->allowed_http_methods);
12   return scalar(grep { lc($_) eq lc($expected) } @allowed) ?
13     1 : 0;
14 }
15
16 around ['match','match_captures'] => sub {
17   my ($orig, $self, $ctx, @args) = @_;
18   return 0 unless $self->$orig($ctx, @args);
19
20   my $expected = $ctx->req->method;
21   return $self->_has_expected_http_method($expected);
22 };
23
24 around 'list_extra_info' => sub {
25   my ($orig, $self, @args) = @_;
26   return {
27     %{ $self->$orig(@args) },
28     HTTP_METHODS => [sort $self->allowed_http_methods],
29   };
30 };
31
32 1;
33
34 =head1 NAME
35
36 Catalyst::ActionRole::HTTPMethods - Match on HTTP Methods
37
38 =head1 SYNOPSIS
39
40     package MyApp::Web::Controller::MyController;
41
42     use Moose;
43     use MooseX::MethodAttributes;
44
45     extends 'Catalyst::Controller';
46
47     sub user_base : Chained('/') CaptureArg(0) { ... }
48
49       sub get_user     : Chained('user_base') Args(1) GET { ... }
50       sub post_user    : Chained('user_base') Args(1) POST { ... }
51       sub put_user     : Chained('user_base') Args(1) PUT { ... }
52       sub delete_user  : Chained('user_base') Args(1) DELETE { ... }
53       sub head_user    : Chained('user_base') Args(1) HEAD { ... }
54       sub options_user : Chained('user_base') Args(1) OPTIONS { ... }
55       sub patch_user   : Chained('user_base') Args(1) PATCH { ... }
56
57
58       sub post_and_put : Chained('user_base') POST PUT Args(1) { ... }
59       sub method_attr  : Chained('user_base') Method('DELETE') Args(0) { ... }
60
61     __PACKAGE__->meta->make_immutable;
62
63 =head1 DESCRIPTION
64
65 This is an action role that lets your L<Catalyst::Action> match on standard
66 HTTP methods, such as GET, POST, etc.
67
68 Since most web browsers have limited support for rich HTTP Method vocabularies
69 we use L<Plack::Middleware::MethodOverride> which allows you to 'tunnel' your
70 request method over POST  This works in two ways.  You can set an extension
71 HTTP header C<X-HTTP-Method-Override> which will contain the value of the
72 desired request method, or you may set a search query parameter
73 C<x-tunneled-method>.  Remember, these only work over HTTP Request type
74 POST.  See L<Plack::Middleware::MethodOverride> for more.
75
76 =head1 REQUIRES
77
78 This role requires the following methods in the consuming class.
79
80 =head2 match
81
82 =head2 match_captures
83
84 Returns 1 if the action matches the existing request and zero if not.
85
86 =head1 METHODS
87
88 This role defines the following methods
89
90 =head2 match
91
92 =head2 match_captures
93
94 Around method modifier that return 1 if the request method matches one of the
95 allowed methods (see L</http_methods>) and zero otherwise.
96
97 =head2 allowed_http_methods
98
99 An array of strings that are the allowed http methods for matching this action
100 normalized as noted above (using X-Method* overrides).
101
102 =head2 list_extra_info
103
104 Adds a key => [@values] "HTTP_METHODS" whose value is an ArrayRef of sorted
105 allowed methods to the ->list_extra_info HashRef.  This is used primarily for
106 debugging output.
107
108 =head2 _has_expected_http_method ($expected)
109
110 Private method which returns 1 if C<$expected> matches one of the allowed
111 in L</http_methods> and zero otherwise.
112
113 =head1 AUTHORS
114
115 Catalyst Contributors, see Catalyst.pm
116
117 =head1 COPYRIGHT
118
119 This library is free software. You can redistribute it and/or modify it under
120 the same terms as Perl itself.
121
122 =cut