line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Catalyst::Action::DeserializeMultiPart; |
2
|
|
|
|
|
|
|
$Catalyst::Action::DeserializeMultiPart::VERSION = '1.19'; |
3
|
6
|
|
|
6
|
|
122254
|
use Moose; |
|
6
|
|
|
|
|
17
|
|
|
6
|
|
|
|
|
54
|
|
4
|
6
|
|
|
6
|
|
35621
|
use namespace::autoclean; |
|
6
|
|
|
|
|
15
|
|
|
6
|
|
|
|
|
57
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
extends 'Catalyst::Action::Deserialize'; |
7
|
6
|
|
|
6
|
|
540
|
use HTTP::Body; |
|
6
|
|
|
|
|
14
|
|
|
6
|
|
|
|
|
1958
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $NO_HTTP_BODY_TYPES_INITIALIZATION; |
10
|
|
|
|
|
|
|
$HTTP::Body::TYPES->{'multipart/mixed'} = 'HTTP::Body::MultiPart' unless $NO_HTTP_BODY_TYPES_INITIALIZATION; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
override execute => sub { |
13
|
|
|
|
|
|
|
my $self = shift; |
14
|
|
|
|
|
|
|
my ( $controller, $c ) = @_; |
15
|
|
|
|
|
|
|
if($c->request->content_type =~ m{^multipart/}i && !defined($c->request->body)){ |
16
|
|
|
|
|
|
|
my $REST_part = $self->attributes->{DeserializePart} || []; |
17
|
|
|
|
|
|
|
my($REST_body) = $c->request->upload($REST_part->[0] || 'REST'); |
18
|
|
|
|
|
|
|
if($REST_body){ |
19
|
|
|
|
|
|
|
$c->request->_body->body( $REST_body->fh ); |
20
|
|
|
|
|
|
|
$c->request->content_type( $REST_body->type ); |
21
|
|
|
|
|
|
|
} |
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
super; |
24
|
|
|
|
|
|
|
}; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
1; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
=head1 NAME |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
Catalyst::Action::DeserializeMultiPart - Deserialize Data in a Multipart Request |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head1 SYNOPSIS |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
package Foo::Controller::Bar; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
__PACKAGE__->config( |
39
|
|
|
|
|
|
|
# see Catalyst::Action::Deserialize for standard config |
40
|
|
|
|
|
|
|
); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub begin :ActionClass('DeserializeMultiPart') DeserializePart('REST') {} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
=head1 DESCRIPTION |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
This action will deserialize multipart HTTP POST, PUT, OPTIONS and DELETE |
47
|
|
|
|
|
|
|
requests. It is a simple extension of L<Catalyst::Action::Deserialize> |
48
|
|
|
|
|
|
|
with the exception that rather than using the entire request body (which |
49
|
|
|
|
|
|
|
may contain multiple sections), it will look for a single part in the request |
50
|
|
|
|
|
|
|
body named according to the C<DeserializePart> attribute on that action |
51
|
|
|
|
|
|
|
(defaulting to C<REST>). If a part is found under that name, it then |
52
|
|
|
|
|
|
|
proceeds to deserialize the request as normal based on the content-type |
53
|
|
|
|
|
|
|
of that individual part. If no such part is found, the request would |
54
|
|
|
|
|
|
|
be processed as if no data was sent. |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
This module's code will only come into play if the following conditions are met: |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=over 4 |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=item * The C<Content-type> of the request is C<multipart/*> |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=item * The request body (as returned by C<$c->request->body> is not defined |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
=item * There is a part of the request body (as returned by C<$c->request->upload($DeserializePart)>) available |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=back |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=head1 CONFIGURING HTTP::Body |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
By default, L<HTTP::Body> parses C<multipart/*> requests as an |
71
|
|
|
|
|
|
|
L<HTTP::Body::OctetStream>. L<HTTP::Body::OctetStream> does not separate |
72
|
|
|
|
|
|
|
out the individual parts of the request body. In order to make use of |
73
|
|
|
|
|
|
|
the individual parts, L<HTTP::Body> must be told which content types |
74
|
|
|
|
|
|
|
to map to L<HTTP::Body::MultiPart>. This module makes the assumption |
75
|
|
|
|
|
|
|
that you would like to have all C<multipart/mixed> requests parsed by |
76
|
|
|
|
|
|
|
L<HTTP::Body::MultiPart> module. This is done by a package variable |
77
|
|
|
|
|
|
|
inside L<HTTP::Body>: C<$HTTP::Body::Types> (a HASH ref). |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
B<WARNING:> As this module modifies the behaviour of HTTP::Body globally, |
80
|
|
|
|
|
|
|
adding it to an application can have unintended consequences as multipart |
81
|
|
|
|
|
|
|
bodies will be parsed differently from before. |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
Feel free to |
84
|
|
|
|
|
|
|
add other content-types to this hash if needed or if you would prefer |
85
|
|
|
|
|
|
|
that C<multipart/mixed> NOT be added to this hash, simply delete it |
86
|
|
|
|
|
|
|
after loading this module. |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# in your controller |
89
|
|
|
|
|
|
|
use Catalyst::Action::DeserializeMultiPart; |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
delete $HTTP::Body::Types->{'multipart/mixed'}; |
92
|
|
|
|
|
|
|
$HTTP::Body::Types->{'multipart/my-crazy-content-type'} = 'HTTP::Body::MultiPart'; |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=head1 SEE ALSO |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
This is a simple sub-class of L<Catalyst::Action::Deserialize>. |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=head1 AUTHORS |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
See L<Catalyst::Action::REST> for authors. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=head1 LICENSE |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
You may distribute this code under the same terms as Perl itself. |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=cut |