use strict;
-use Carp qw[ ];
-use List::Util qw[ first ];
-use Scalar::Util qw[ blessed ];
+use Carp qw[ ];
+use List::Util qw[ first ];
our $PARSERS = {
'application/octet-stream' => 'HTTP::Body::Octetstream',
buffer => '',
content_length => $content_length,
content_type => $content_type,
+ length => 0,
param => { },
upload => { }
};
}
sub add {
- Carp::croak('Define abstract method add() in implementation');
-}
-
-sub init {
- return $_[0];
+ my $self = shift;
+
+ if ( defined $_[0] ) {
+ $self->{buffer} .= $_[0];
+ $self->{length} += length($_[0]);
+ }
+
+ $self->spin;
+
+ return ( $self->length - $self->content_length );
}
sub body {
return $self->{body};
}
+sub buffer {
+ return shift->{buffer};
+}
+
sub content_length {
return shift->{content_length};
}
return shift->{content_type};
}
+sub init {
+ return $_[0];
+}
+
+sub length {
+ return shift->{length};
+}
+
+sub spin {
+ Carp::croak('Define abstract method spin() in implementation');
+}
+
sub param {
my $self = shift;
$self->{boundary} = $1;
$self->{state} = 'preamble';
- $self->{length} = $self->content_length - $self->content_length * 2;
return $self;
}
-sub add {
- my ( $self, $buffer ) = @_;
-
- unless ( defined $buffer ) {
- $buffer = '';
- }
-
- $self->{buffer} .= $buffer;
- $self->{length} += length($buffer);
+sub spin {
+ my $self = shift;
while (1) {
elsif ( $self->{state} =~ /^(preamble|boundary|header|body)$/ ) {
my $method = "parse_$1";
- return $self->{length} unless $self->$method;
+ return unless $self->$method;
}
else {
}
sub boundary {
- my $self = shift;
- $self->{boundary} = shift if @_;
- return $self->{boundary};
+ return shift->{boundary};
}
sub boundary_begin {
if ( index( $self->{buffer}, $self->delimiter_begin . $self->crlf ) == 0 ) {
substr( $self->{buffer}, 0, length( $self->delimiter_begin ) + 2, '' );
- $self->{current} = {};
- $self->{state} = 'header';
+ $self->{part} = {};
+ $self->{state} = 'header';
return 1;
}
if ( index( $self->{buffer}, $self->delimiter_end . $self->crlf ) == 0 ) {
- $self->{current} = {};
- $self->{state} = 'done';
+
+ substr( $self->{buffer}, 0, length( $self->delimiter_end ) + 2, '' );
+ $self->{part} = {};
+ $self->{state} = 'done';
+
return 0;
- }
+ }
return 0;
}
( my $field = $1 ) =~ s/\b(\w)/uc($1)/eg;
- if ( exists $self->{current}->{headers}->{$field} ) {
- for ( $self->{current}->{headers}->{$field} ) {
+ if ( exists $self->{part}->{headers}->{$field} ) {
+ for ( $self->{part}->{headers}->{$field} ) {
$_ = [$_] unless ref($_) eq "ARRAY";
push( @$_, $header );
}
}
else {
- $self->{current}->{headers}->{$field} = $header;
+ $self->{part}->{headers}->{$field} = $header;
}
}
return 0;
}
- $self->{current}->{data} .= substr( $self->{buffer}, 0, $length, '' );
- $self->{current}->{size} += $length;
- $self->{current}->{done} = 0;
+ $self->{part}->{data} .= substr( $self->{buffer}, 0, $length, '' );
+ $self->{part}->{size} += $length;
+ $self->{part}->{done} = 0;
- $self->handler( $self->{current} );
+ $self->handler( $self->{part} );
return 0;
}
- $self->{current}->{data} .= substr( $self->{buffer}, 0, $index, '' );
- $self->{current}->{size} += $index;
- $self->{current}->{done} = 1;
+ $self->{part}->{data} .= substr( $self->{buffer}, 0, $index, '' );
+ $self->{part}->{size} += $index;
+ $self->{part}->{done} = 1;
- $self->handler( $self->{current} );
+ $self->handler( $self->{part} );
$self->{state} = 'boundary';
if ( $part->{filename} ) {
- my $fh = delete $part->{fh};
- $fh->close;
+ $part->{fh}->close;
+
+ delete @{ $part }{ qw[ done fh ] };
$self->upload( $part->{name}, $part );
}
my $headers = LoadFile( sprintf( "t/data/multipart/%.3d-headers.yml", $test ) );
my $content = IO::File->new( sprintf( "t/data/multipart/%.3d-content.dat", $test ), O_RDONLY );
-my $parser = HTTP::Body->new( $headers->{'Content-Type'}, $headers->{'Content-Length'} );
-
-warn ref($parser);
+my $body = HTTP::Body->new( $headers->{'Content-Type'}, $headers->{'Content-Length'} );
binmode $content;
while ( $content->read( my $buffer, 1024 ) ) {
- last if $parser->add($buffer) == 0;
+ $body->add($buffer);
}
-warn "length : $parser->{length}\n";
-warn "state : $parser->{state}\n";
+warn Dumper( $body->param );
+warn Dumper( $body->upload );
+warn Dumper( $body->body );
-warn Dumper( $parser->param );
-warn Dumper( $parser->upload );
+warn "length : " . $body->length;
+warn "content length : " . $body->content_length;
+warn "state : " . $body->{state};
+warn "buffer : " . $body->buffer;