8 'application/octet-stream' => 'HTTP::Body::OctetStream',
9 'application/x-www-form-urlencoded' => 'HTTP::Body::UrlEncoded',
10 'multipart/form-data' => 'HTTP::Body::MultiPart',
11 'multipart/related' => 'HTTP::Body::XFormsMultipart',
12 'application/xml' => 'HTTP::Body::XForms',
13 'application/json' => 'HTTP::Body::OctetStream',
16 require HTTP::Body::OctetStream;
17 require HTTP::Body::UrlEncoded;
18 require HTTP::Body::MultiPart;
19 require HTTP::Body::XFormsMultipart;
20 require HTTP::Body::XForms;
27 HTTP::Body - HTTP Body Parser
33 sub handler : method {
34 my ( $class, $r ) = @_;
36 my $content_type = $r->headers_in->get('Content-Type');
37 my $content_length = $r->headers_in->get('Content-Length');
39 my $body = HTTP::Body->new( $content_type, $content_length );
40 my $length = $content_length;
44 $r->read( my $buffer, ( $length < 8192 ) ? $length : 8192 );
46 $length -= length($buffer);
51 my $uploads = $body->upload; # hashref
52 my $params = $body->param; # hashref
53 my $param_order = $body->param_order # arrayref
54 my $body = $body->body; # IO::Handle
59 HTTP::Body parses chunks of HTTP POST data and supports
60 application/octet-stream, application/json, application/x-www-form-urlencoded,
61 and multipart/form-data.
63 Chunked bodies are supported by not passing a length value to new().
65 It is currently used by L<Catalyst>, L<Dancer>, L<Maypole>, L<Web::Simple> and
70 When parsing multipart bodies, temporary files are created to store any
71 uploaded files. You must delete these temporary files yourself after
72 processing them, or set $body->cleanup(1) to automatically delete them at
75 With version 1.23, we have changed the basic behavior of how temporary files
76 are prepared for uploads. The extension of the file is no longer transferred
77 to the temporary file, the extension will always be C<.upload>. We have also
78 introduced variables that make it possible to set the behavior as required.
82 =item $HTTP::Body::MultiPart::file_temp_suffix
84 This is the extension that is given to all multipart files. The default
85 setting here is C<.upload>. If you want the old behavior from before version
86 1.23, simply undefine the value here.
88 =item $HTTP::Body::MultiPart::basename_regexp
90 This is the regexp used to determine out the file extension. This is of
91 course no longer necessary, unless you undefine
92 C<HTTP::Body::MultiPart::file_temp_suffix>.
94 =item $HTTP::Body::MultiPart::file_temp_template
96 This gets passed through to the L<File::Temp> TEMPLATE parameter. There is no
97 special default in our module.
99 =item %HTTP::Body::MultiPart::file_temp_parameters
101 In this hash you can add up custom settings for the L<File::Temp> invokation.
102 Those override every other setting.
112 Constructor. Takes content type and content length as parameters,
113 returns a L<HTTP::Body> object.
118 my ( $class, $content_type, $content_length ) = @_;
121 Carp::croak( $class, '->new( $content_type, [ $content_length ] )' );
126 foreach my $supported ( keys %{$TYPES} ) {
127 my $index = index( lc($content_type), $supported );
128 if ($index >= 0 && (!defined $earliest_index || $index < $earliest_index)) {
130 $earliest_index = $index;
134 my $body = $TYPES->{ $type || 'application/octet-stream' };
141 chunked => !defined $content_length,
142 content_length => defined $content_length ? $content_length : -1,
143 content_type => $content_type,
147 state => 'buffering',
150 tmpdir => File::Spec->tmpdir(),
153 bless( $self, $body );
161 if ( $self->{cleanup} ) {
163 for my $upload ( values %{ $self->{upload} } ) {
164 push @temps, map { $_->{tempname} || () }
165 ( ref $upload eq 'ARRAY' ? @{$upload} : $upload );
168 unlink map { $_ } grep { -e $_ } @temps;
174 Add string to internal buffer. Will call spin unless done. returns
175 length before adding self.
182 if ( $self->{chunked} ) {
183 $self->{chunk_buffer} .= $_[0];
185 while ( $self->{chunk_buffer} =~ m/^([\da-fA-F]+).*\x0D\x0A/ ) {
186 my $chunk_len = hex($1);
188 if ( $chunk_len == 0 ) {
190 $self->{chunk_buffer} =~ s/^([\da-fA-F]+).*\x0D\x0A//;
192 # End of data, there may be trailing headers
193 if ( my ($headers) = $self->{chunk_buffer} =~ m/(.*)\x0D\x0A/s ) {
194 if ( my $message = HTTP::Message->parse( $headers ) ) {
195 $self->{trailing_headers} = $message->headers;
199 $self->{chunk_buffer} = '';
201 # Set content_length equal to the amount of data we read,
202 # so the spin methods can finish up.
203 $self->{content_length} = $self->{length};
206 # Make sure we have the whole chunk in the buffer (+CRLF)
207 if ( length( $self->{chunk_buffer} ) >= $chunk_len ) {
209 $self->{chunk_buffer} =~ s/^([\da-fA-F]+).*\x0D\x0A//;
211 # Pull chunk data out of chunk buffer into real buffer
212 $self->{buffer} .= substr $self->{chunk_buffer}, 0, $chunk_len, '';
214 # Strip remaining CRLF
215 $self->{chunk_buffer} =~ s/^\x0D\x0A//;
217 $self->{length} += $chunk_len;
220 # Not enough data for this chunk, wait for more calls to add()
225 unless ( $self->{state} eq 'done' ) {
233 my $cl = $self->content_length;
235 if ( defined $_[0] ) {
236 $self->{length} += length( $_[0] );
238 # Don't allow buffer data to exceed content-length
239 if ( $self->{length} > $cl ) {
240 $_[0] = substr $_[0], 0, $cl - $self->{length};
241 $self->{length} = $cl;
244 $self->{buffer} .= $_[0];
247 unless ( $self->state eq 'done' ) {
251 return ( $self->length - $cl );
256 accessor for the body.
262 $self->{body} = shift if @_;
263 return $self->{body};
268 Returns 1 if the request is chunked.
273 return shift->{chunked};
278 Set to 1 to enable automatic deletion of temporary files at DESTROY-time.
284 $self->{cleanup} = shift if @_;
285 return $self->{cleanup};
290 Returns the content-length for the body data if known.
291 Returns -1 if the request is chunked.
296 return shift->{content_length};
301 Returns the content-type of the body data.
306 return shift->{content_type};
321 Returns the total length of data we expect to read if known.
322 In the case of a chunked request, returns the amount of data
328 return shift->{length};
331 =item trailing_headers
333 If a chunked request body had trailing headers, trailing_headers will
334 return an HTTP::Headers object populated with those headers.
338 sub trailing_headers {
339 return shift->{trailing_headers};
344 Abstract method to spin the io handle.
349 Carp::croak('Define abstract method spin() in implementation');
354 Returns the current state of the parser.
360 $self->{state} = shift if @_;
361 return $self->{state};
366 Get/set body parameters.
375 my ( $name, $value ) = @_;
377 if ( exists $self->{param}->{$name} ) {
378 for ( $self->{param}->{$name} ) {
379 $_ = [$_] unless ref($_) eq "ARRAY";
384 $self->{param}->{$name} = $value;
387 push @{$self->{param_order}}, $name;
390 return $self->{param};
395 Get/set file uploads.
404 my ( $name, $upload ) = @_;
406 if ( exists $self->{upload}->{$name} ) {
407 for ( $self->{upload}->{$name} ) {
408 $_ = [$_] unless ref($_) eq "ARRAY";
409 push( @$_, $upload );
413 $self->{upload}->{$name} = $upload;
417 return $self->{upload};
422 Just like 'param' but gives you a hash of the full data associated with the
423 part in a multipart type POST/PUT. Example:
429 "Content-Disposition" => "form-data; name=\"arg2\"",
430 "Content-Type" => "text/plain"
443 my ( $name, $data ) = @_;
445 if ( exists $self->{part_data}->{$name} ) {
446 for ( $self->{part_data}->{$name} ) {
447 $_ = [$_] unless ref($_) eq "ARRAY";
452 $self->{part_data}->{$name} = $data;
456 return $self->{part_data};
461 Specify a different path for temporary files. Defaults to the system temporary path.
467 $self->{tmpdir} = shift if @_;
468 return $self->{tmpdir};
473 Returns the array ref of the param keys in the order how they appeared on the body
478 return shift->{param_order};
485 Since its original creation this module has been taken over by the Catalyst
486 development team. If you need general support using this module:
490 Join #catalyst on irc.perl.org.
494 http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
496 If you want to contribute patches, these will be your
497 primary contact points:
501 Join #catalyst-dev on irc.perl.org.
505 http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev
509 Christian Hansen, C<chansen@cpan.org>
511 Sebastian Riedel, C<sri@cpan.org>
513 Andy Grundman, C<andy@hybridized.org>
517 Simon Elliott C<cpan@papercreatures.com>
519 Kent Fredric C<kentnl@cpan.org>
521 Christian Walde C<walde.christian@gmail.com>
523 Torsten Raudssus C<torsten@raudssus.de>
527 This library is free software. You can redistribute it and/or modify
528 it under the same terms as perl itself.