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