created HTTP::Body::Urlencoded
[catagits/HTTP-Body.git] / lib / HTTP / Body.pm
1 package HTTP::Body;
2
3 use strict;
4
5 use Carp       qw[ ];
6 use List::Util qw[ first ];
7
8 our $TYPES = {
9     'application/octet-stream'          => 'HTTP::Body::Octetstream',
10     'application/x-www-form-urlencoded' => 'HTTP::Body::Urlencoded',
11     'multipart/form-data'               => 'HTTP::Body::Multipart'
12 };
13
14 sub new {
15     my ( $class, $content_type, $content_length ) = @_;
16
17     unless ( @_ == 3 ) {
18         Carp::croak( $class, '->new( $content_type, $content_length )' );
19     }
20
21     my $type = first { index( lc($content_type), $_ ) >= 0 } keys %{$TYPES};
22     my $body = $TYPES->{ $type || 'application/octet-stream' };
23
24     eval "require $body";
25
26     if ($@) {
27         die $@;
28     }
29
30     my $self = {
31         buffer         => '',
32         content_length => $content_length,
33         content_type   => $content_type,
34         length         => 0,
35         param          => {},
36         state          => 'buffering',
37         upload         => {}
38     };
39
40     bless( $self, $body );
41
42     return $self->init;
43 }
44
45 sub add {
46     my $self = shift;
47
48     if ( defined $_[0] ) {
49         $self->{buffer} .= $_[0];
50         $self->{length} += length( $_[0] );
51     }
52     
53     unless ( $self->state eq 'done' ) {
54         $self->spin;
55     }
56
57     return ( $self->length - $self->content_length );
58 }
59
60 sub body {
61     my $self = shift;
62     $self->{body} = shift if @_;
63     return $self->{body};
64 }
65
66 sub buffer {
67     return shift->{buffer};
68 }
69
70 sub content_length {
71     return shift->{content_length};
72 }
73
74 sub content_type {
75     return shift->{content_type};
76 }
77
78 sub init {
79     return $_[0];
80 }
81
82 sub length {
83     return shift->{length};
84 }
85
86 sub spin {
87     Carp::croak('Define abstract method spin() in implementation');
88 }
89
90 sub state {
91     my $self = shift;
92     $self->{state} = shift if @_;
93     return $self->{state};    
94 }
95
96 sub param {
97     my $self = shift;
98
99     if ( @_ == 2 ) {
100
101         my ( $name, $value ) = @_;
102
103         if ( exists $self->{param}->{$name} ) {
104             for ( $self->{param}->{$name} ) {
105                 $_ = [$_] unless ref($_) eq "ARRAY";
106                 push( @$_, $value );
107             }
108         }
109         else {
110             $self->{param}->{$name} = $value;
111         }
112     }
113
114     return $self->{param};
115 }
116
117 sub upload {
118     my $self = shift;
119
120     if ( @_ == 2 ) {
121
122         my ( $name, $upload ) = @_;
123
124         if ( exists $self->{upload}->{$name} ) {
125             for ( $self->{upload}->{$name} ) {
126                 $_ = [$_] unless ref($_) eq "ARRAY";
127                 push( @$_, $upload );
128             }
129         }
130         else {
131             $self->{upload}->{$name} = $upload;
132         }
133     }
134
135     return $self->{upload};
136 }
137
138 1;