1 package HTTP::Body::Parser;
6 use base 'Class::Accessor::Fast';
10 use HTTP::Headers qw[];
11 use Params::Validate qw[];
13 __PACKAGE__->mk_accessors( qw[ bufsize context seen_eos ] );
18 my ( $content_type, $parser ) = ( @_ == 2 ) ? @_[ 1, 0 ] : @_[ 1, 2 ];
20 $PARSERS->{ $content_type } = $parser;
22 eval "use prefork '$parser';";
25 __PACKAGE__->register_parser( 'application/octet-stream' => 'HTTP::Body::Parser::OctetStream' );
26 __PACKAGE__->register_parser( 'application/x-www-form-urlencoded' => 'HTTP::Body::Parser::UrlEncoded' );
27 __PACKAGE__->register_parser( 'multipart/form-data' => 'HTTP::Body::Parser::MultiPart' );
30 my $class = ref $_[0] ? ref shift : shift;
31 my $params = Params::Validate::validate_with(
35 type => Params::Validate::SCALAR,
40 type => Params::Validate::OBJECT,
41 isa => 'HTTP::Body::Context',
45 called => "$class\::new"
49 if ( $class ne __PACKAGE__ ) {
50 return bless( {}, $class )->initialize($params);
54 my $content_type = $params->{context}->content_type;
56 Carp::croak qq/Mandatory header 'Content-Type' is missing from headers in context./
57 unless defined $content_type;
59 my $parser = $PARSERS->{ lc $content_type } || $PARSERS->{ 'application/octet-stream' };
61 eval "require $parser;"
62 or Carp::croak qq/Failed to load parser '$parser' for Content-Type '$content_type'. Reason '$@'/;
64 return $parser->new($params);
68 my ( $self, $params ) = @_;
70 $params->{buffer} = '';
71 $params->{length} = 0;
72 $params->{seen_eos} = 0;
74 while ( my ( $param, $value ) = each( %{ $params } ) ) {
75 $self->$param($value);
85 $self->{buffer} = $_[0];
95 $self->{length} = $_[0];
106 if ( $self->context->content_length ) {
108 my $expected = $self->context->content_length;
109 my $length = $self->length;
111 if ( $length < $expected ) {
112 Carp::croak qq/Truncated body. Expected $expected bytes, but only got $length bytes./;
122 if ( defined $_[0] ) {
123 $self->length += bytes::length $_[0];
124 $self->buffer .= $_[0];