File Coverage

blib/lib/Catalyst/ActionRole/ConsumesContent.pm
Criterion Covered Total %
statement 18 18 100.0
branch 6 6 100.0
condition n/a
subroutine 4 4 100.0
pod 1 1 100.0
total 29 29 100.0


line stmt bran cond sub pod time code
1              
2             use Moose::Role;
3 4     4   3229  
  4         12  
  4         33  
4             requires 'match', 'match_captures', 'list_extra_info';
5              
6             has allowed_content_types => (
7             is=>'ro',
8             required=>1,
9             lazy=>1,
10             isa=>'ArrayRef',
11             builder=>'_build_allowed_content_types');
12              
13             has normalized => (
14             is=>'ro',
15             required=>1,
16             lazy=>1,
17             isa=>'HashRef',
18             builder=>'_build_normalized');
19              
20              
21             return +{
22             JSON => 'application/json',
23             JS => 'application/javascript',
24 13     13   523 PERL => 'application/perl',
25             HTML => 'text/html',
26             XML => 'text/XML',
27             Plain => 'text/plain',
28             UrlEncoded => 'application/x-www-form-urlencoded',
29             Multipart => 'multipart/form-data',
30             HTMLForm => ['application/x-www-form-urlencoded','multipart/form-data'],
31             };
32             }
33              
34             my $self = shift;
35             my @proto = map {split ',', $_ } @{$self->attributes->{Consumes}};
36             my @converted = map {
37 13     13   39 if(my $normalized = $self->normalized->{$_}) {
38 13         26 ref $normalized ? @$normalized : ($normalized);
  14         66  
  13         357  
39             } else {
40 13 100       32 $_;
  15         578  
41 8 100       42 }
42             } @proto;
43 7         22  
44             return \@converted;
45             }
46              
47 13         443 around ['match','match_captures'] => sub {
48             my ($orig, $self, $ctx, @args) = @_;
49             if(my $content_type = $ctx->req->content_type) {
50             return 0 unless $self->can_consume($content_type);
51             }
52             return $self->$orig($ctx, @args);
53             };
54              
55             my ($self, $request_content_type) = @_;
56             my @matches = grep { lc($_) eq lc($request_content_type) }
57             @{$self->allowed_content_types};
58             return @matches ? 1:0;
59 57     57 1 134 }
60 63         234  
61 57         98 around 'list_extra_info' => sub {
  57         2022  
62 57 100       375 my ($orig, $self, @args) = @_;
63             return {
64             %{ $self->$orig(@args) },
65             CONSUMES => $self->allowed_content_types,
66             };
67             };
68              
69             1;
70              
71             =head1 NAME
72              
73             Catalyst::ActionRole::ConsumesContent - Match on HTTP Request Content-Type
74              
75             =head1 SYNOPSIS
76              
77             package MyApp::Web::Controller::MyController;
78              
79             use base 'Catalyst::Controller';
80              
81             sub start : POST Chained('/') CaptureArg(0) { ... }
82              
83             sub is_json : Chained('start') Consumes('application/json') { ... }
84             sub is_urlencoded : Chained('start') Consumes('application/x-www-form-urlencoded') { ... }
85             sub is_multipart : Chained('start') Consumes('multipart/form-data') { ... }
86              
87             ## Alternatively, for common types...
88              
89             sub is_json : Chained('start') Consume(JSON) { ... }
90             sub is_urlencoded : Chained('start') Consumes(UrlEncoded) { ... }
91             sub is_multipart : Chained('start') Consumes(Multipart) { ... }
92              
93             ## Or allow more than one type
94              
95             sub is_more_than_one
96             : Chained('start')
97             : Consumes('application/x-www-form-urlencoded')
98             : Consumes('multipart/form-data')
99             {
100             ## ...
101             }
102              
103             1;
104              
105             =head1 DESCRIPTION
106              
107             This is an action role that lets your L<Catalyst::Action> match on the content
108             type of the incoming request.
109              
110             Generally when there's a PUT or POST request, there's a request content body
111             with a matching MIME content type. Commonly this will be one of the types
112             used with classic HTML forms ('application/x-www-form-urlencoded' for example)
113             but there's nothing stopping you specifying any valid content type.
114              
115             For matching purposes, we match strings but the casing is insensitive.
116              
117             =head1 REQUIRES
118              
119             This role requires the following methods in the consuming class.
120              
121             =head2 match
122              
123             =head2 match_captures
124              
125             Returns 1 if the action matches the existing request and zero if not.
126              
127             =head1 METHODS
128              
129             This role defines the following methods
130              
131             =head2 match
132              
133             =head2 match_captures
134              
135             Around method modifier that return 1 if the request content type matches one of the
136             allowed content types (see L</http_methods>) and zero otherwise.
137              
138             =head2 allowed_content_types
139              
140             An array of strings that are the allowed content types for matching this action.
141              
142             =head2 can_consume
143              
144             Boolean. Does the current request match content type with what this actionrole
145             can consume?
146              
147             =head2 list_extra_info
148              
149             Add the accepted content type to the debug screen.
150              
151             =head1 AUTHORS
152              
153             Catalyst Contributors, see Catalyst.pm
154              
155             =head1 COPYRIGHT
156              
157             This library is free software. You can redistribute it and/or modify it under
158             the same terms as Perl itself.
159              
160             =cut