File Coverage

lib/HTTP/Promise/Parser.pm
Criterion Covered Total %
statement 403 530 76.0
branch 144 280 51.4
condition 89 217 41.0
subroutine 40 54 74.0
pod 31 33 93.9
total 707 1114 63.4


line stmt bran cond sub pod time code
1             ##----------------------------------------------------------------------------
2             ## Asynchronous HTTP Request and Promise - ~/lib/HTTP/Promise/Parser.pm
3             ## Version v0.2.0
4             ## Copyright(c) 2022 DEGUEST Pte. Ltd.
5             ## Author: Jacques Deguest <jack@deguest.jp>
6             ## Created 2022/03/25
7             ## Modified 2023/09/08
8             ## All rights reserved.
9             ##
10             ##
11             ## This program is free software; you can redistribute it and/or modify it
12             ## under the same terms as Perl itself.
13             ##----------------------------------------------------------------------------
14             package HTTP::Promise::Parser;
15             BEGIN
16             {
17 11     11   1574188 use strict;
  11         63  
  11         365  
18 11     11   75 use warnings;
  11         50  
  11         401  
19 11     11   71 use warnings::register;
  11         41  
  11         1692  
20 11     11   107 use parent qw( Module::Generic );
  11         19  
  11         106  
21 11         2008 use vars qw( @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION $ERROR $DEBUG $EXCEPTION_CLASS
22             $CRLF $LWS $TEXT $TOKEN $HEADER $HTTP_VERSION $REQUEST $RESPONSE
23             $MAX_HEADERS_SIZE $MAX_READ_BUFFER $MAX_BODY_IN_MEMORY_SIZE
24 11     11   100418 $DEFAULT_MIME_TYPE );
  11         30  
25 11     11   98 use version;
  11         36  
  11         167  
26             # use HTTP::Parser::XS 0.17 ();
27 11     11   6264 use HTTP::Parser2::XS 0.01 ();
  11         5532  
  11         306  
28 11     11   7953 use HTTP::Promise::Entity;
  11         41  
  11         132  
29 11     11   3905 use HTTP::Promise::Headers;
  11         35  
  11         345  
30 11     11   4536 use HTTP::Promise::IO;
  11         55  
  11         134  
31 11     11   3217 use Module::Generic::File qw( sys_tmpdir );
  11         29  
  11         117  
32             # use Nice::Try;
33 11     11   3217 use URI;
  11         28  
  11         331  
34 11     11   5073 use URI::Encode::XS;
  11         5964  
  11         568  
35 11     11   83 use Want;
  11         28  
  11         698  
36             use constant (
37 11         5066 TYPE_URL_ENCODED => 'application/x-www-form-urlencoded',
38 11     11   76 );
  11         33  
39 11     11   57 our @EXPORT = ();
40 11         51 our @EXPORT_OK = qw( parse_headers parse_request parse_request_line parse_response
41             parse_response_line parse_version );
42 11         106 our %EXPORT_TAGS = (
43             'all' => [@EXPORT_OK],
44             'request' => [qw( parse_headers parse_request parse_request_line parse_version )],
45             'response' => [qw( parse_headers parse_response parse_response_line parse_version )],
46             );
47             # rfc2616, section 2.2 on basic rules
48             # <https://tools.ietf.org/html/rfc2616#section-2.2>
49 11         132 our $CRLF = qr/\x0D?\x0A/;
50 11         364 our $LWS = qr/$CRLF[\x09\x20]|[\x09\x20]/;
51 11         50 our $TEXT = qr/[\x20-\xFF]/;
52             # !, #, $, %, &, ', *, +, -, ., 0..9, A..Z, ^, _, `, a..z, |, ~
53 11         43 our $TOKEN = qr/[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]/;
54             # rfc2616, section 4.2 on message headers
55             # <https://tools.ietf.org/html/rfc2616#section-4.2>
56             # rfc7230, section 3.2
57             # <https://tools.ietf.org/html/rfc7230#section-3.2>
58 11         703 our $HEADER = qr/($TOKEN+)$LWS*:$LWS*((?:$TEXT|$LWS)*)$CRLF/;
59             # HTTP/1.0, HTTP/1.1, HTTP/2
60 11         76 our $HTTP_VERSION = qr/(?<http_protocol>HTTP\/(?<http_version>(?<http_vers_major>[0-9])(?:\.(?<http_vers_minor>[0-9]))?))/;
61             # rfc7230 superseding rfc2616 on request line
62             # <https://tools.ietf.org/html/rfc7230#page-21>
63 11         551 our $REQUEST = qr/(?<method>$TOKEN+)[\x09\x20]+(?<uri>[\x21-\xFF]+)[\x09\x20]+(?<protocol>$HTTP_VERSION)$CRLF/;
64 11         561 our $REQUEST_RFC2616 = qr/(?:$CRLF)*($TOKEN+)[\x09\x20]+([\x21-\xFF]+)(?:[\x09\x20]+($HTTP_VERSION))?$CRLF/;
65 11         511 our $RESPONSE = qr/(?<protocol>$HTTP_VERSION)[\x09\x20]+(?<code>[0-9]{3})[\x09\x20]+(?<status>$TEXT*)$CRLF/;
66             # 8Kb
67             # Beyond this, we return a 413 Entity Too Large
68             # Ref: <https://stackoverflow.com/questions/686217/maximum-on-http-header-values>
69 11         59 our $MAX_HEADERS_SIZE = 8192;
70 11         39 our $MAX_READ_BUFFER = 2048;
71             # 100Kb
72 11         25 our $MAX_BODY_IN_MEMORY_SIZE = 102400;
73 11         38 our $DEFAULT_MIME_TYPE = 'application/octet-stream';
74 11         35 our $ERROR = '';
75 11         24 our $DEBUG = 0;
76 11         20 our $EXCEPTION_CLASS = 'HTTP::Promise::Exception';
77 11         391 our $VERSION = 'v0.2.0';
78             };
79              
80 11     11   75 use strict;
  11         52  
  11         439  
81 11     11   69 use warnings;
  11         24  
  11         77969  
82              
83             sub init
84             {
85 35     35 1 1204209 my $self = shift( @_ );
86 35         1181 $self->{decode_body} = 1;
87 35         167 $self->{decode_headers} = 0;
88 35         108 $self->{ignore_filename}= 0;
89 35         190 $self->{max_body_in_memory_size} = $MAX_BODY_IN_MEMORY_SIZE;
90 35         125 $self->{max_headers_size} = $MAX_HEADERS_SIZE;
91 35         104 $self->{max_read_buffer} = $MAX_READ_BUFFER;
92 35         287 $self->{output_dir} = sys_tmpdir();
93 35         5061986 $self->{tmp_dir} = undef;
94 35         201 $self->{tmp_to_core} = 0;
95 35         190 $self->{_init_strict_use_sub} = 1;
96 35         229 $self->{_exception_class} = $EXCEPTION_CLASS;
97 35 50       757 $self->SUPER::init( @_ ) || return( $self->pass_error );
98 35         6354 my $dir = $self->output_dir;
99 35 50 33     31693 return( $self->error( "No output directory set." ) ) if( !defined( $dir ) || !length( $dir ) );
100 35 50       1212 return( $self->error( "Output directory set \"$dir\" does not exist." ) ) if( !$dir->exists );
101 35 50       3037 return( $self->error( "Output directory set \"$dir\" is not actually a directory." ) ) if( !$dir->is_dir );
102 35         2425 return( $self );
103             }
104              
105 4     4 1 142642 sub decode_body { return( shift->_set_get_boolean( 'decode_body', @_ ) ); }
106              
107 0     0 1 0 sub decode_headers { return( shift->_set_get_boolean( 'decode_headers', @_ ) ); }
108              
109 0     0 1 0 sub ignore_filename { return( shift->_set_get_boolean( 'ignore_filename', @_ ) ); }
110              
111             sub looks_like_request
112             {
113 0     0 1 0 my $self = shift( @_ );
114 0         0 my $this = shift( @_ );
115 0 0 0     0 return( $self->error( "Invalid argument. You can only provide either a string or a scalar reference." ) ) if( ref( $this ) && !$self->_is_scalar( $this ) );
116 0 0       0 my $ref = $self->_is_scalar( $this ) ? $this : \$this;
117 0 0       0 if( $$ref =~ /^$REQUEST/ )
118             {
119 0         0 my $def = {%+};
120 0         0 return( $def );
121             }
122             else
123             {
124             # undef is for errors
125 0         0 return( '' );
126             }
127             }
128              
129             sub looks_like_response
130             {
131 0     0 1 0 my $self = shift( @_ );
132 0         0 my $this = shift( @_ );
133 0 0 0     0 return( $self->error( "Invalid argument. You can only provide either a string or a scalar reference." ) ) if( ref( $this ) && !$self->_is_scalar( $this ) );
134 0 0       0 my $ref = $self->_is_scalar( $this ) ? $this : \$this;
135 0 0       0 if( $$ref =~ /^$RESPONSE/ )
136             {
137 0         0 my $def = {%+};
138 0         0 return( $def );
139             }
140             else
141             {
142             # undef is for errors
143 0         0 return( '' );
144             }
145             }
146              
147             sub looks_like_what
148             {
149 2     2 1 20 my $self = shift( @_ );
150 2         24 my $this = shift( @_ );
151             # Shortcut
152 2 50       34 return( '' ) if( !defined( $this ) );
153 2 50 33     34 return( $self->error( "Invalid argument. You can only provide either a string or a scalar reference." ) ) if( ref( $this ) && !$self->_is_scalar( $this ) );
154 2 50       31 my $ref = $self->_is_scalar( $this ) ? $this : \$this;
155             # No need to go further
156 2 50 33     72 return( '' ) if( !defined( $$ref ) || !length( $$ref ) );
157 2         12 my( $type, $def );
158 2 100       263 if( $$ref =~ /^$REQUEST/ )
    50          
159             {
160 1         95 $def = {%+};
161 1         15 $type = 'request';
162             }
163             elsif( $$ref =~ /^$RESPONSE/ )
164             {
165 1         41 $def = {%+};
166 1         11 $type = 'response';
167             }
168             # undef is for errors
169 2 50       34 return( '' ) if( !defined( $def ) );
170 2         21 $def->{type} = $type;
171 2         16 return( $def );
172             }
173              
174 27     27 1 163 sub max_body_in_memory_size { return( shift->_set_get_number( 'max_body_in_memory_size', @_ ) ); }
175              
176 32     32 1 240 sub max_headers_size { return( shift->_set_get_number( 'max_headers_size', @_ ) ); }
177              
178 20     20 1 518 sub max_read_buffer { return( shift->_set_get_number( 'max_read_buffer', @_ ) ); }
179              
180             sub new_tmpfile
181             {
182 0     0 1 0 my $self = shift( @_ );
183 0         0 my $io;
184 0 0       0 if( $self->tmp_to_core )
185             {
186 0         0 my $var = $self->new_scalar;
187 0   0     0 $io = $var->open( '+>' ) || return( $self->pass_error( $var->error ) );
188             }
189             else
190             {
191 0         0 my $tmpdir = $self->tmp_dir;
192 0   0     0 $io = $self->new_tempfile( $tmpdir ? ( dir => $tmpdir ) : () ) ||
193             return( $self->pass_error );
194 0 0       0 $io->open( '>', { binmode => 'raw', autoflush => 1 } ) || return( $self->pass_error( $io->error ) );
195             }
196 0         0 return( $io );
197             }
198              
199 37     37 1 706 sub output_dir { return( shift->_set_get_file( 'output_dir', @_ ) ); }
200              
201             sub parse
202             {
203 23     23 1 64643 my $self = shift( @_ );
204 23   50     194 my $this = shift( @_ ) || return( $self->error( "Nothing to parse was provided." ) );
205             # Can be glob, scalar reference, file path
206 23         127 my $io;
207 23 100       259 if( $self->_is_glob( $this ) )
    100          
208             {
209 4         106 $io = $this;
210             }
211             elsif( $self->_is_scalar( $this ) )
212             {
213 17 50       813 $self->_load_class( 'Module::Generic::Scalar::IO' ) ||
214             return( $self->pass_error );
215 17   50     8936 $io = Module::Generic::Scalar::IO->new( $this, '<' ) ||
216             return( $self->pass_error( Module::Generic::Scalar::IO->error ) );
217             }
218             else
219             {
220 2   50     122 my $f = $self->new_file( $this ) || return( $self->pass_error );
221 2   100     271159 $io = $f->open( '<', { binmode => 'raw' } ) || return( $self->pass_error( $f->error ) );
222             }
223 22         24333 return( $self->parse_fh( $io, @_ ) );
224             }
225              
226             sub parse_data
227             {
228 1     1 1 4182 my $self = shift( @_ );
229 1 50 33     22 return( $self->error( "Invalid argument. parse_data() only accepts either a string or something that stringifies." ) ) if( ref( $_[0] ) && !overload::Method( $_[0] => '""' ) );
230 1         23 return( $self->parse( \"$_[0]" ) );
231             }
232              
233             sub parse_fh
234             {
235 22     22 1 138 my $self = shift( @_ );
236 22         83 my $fh = shift( @_ );
237 22 50       123 return( $self->error( "No filehandle was provided to read from." ) ) if( !defined( $fh ) );
238 22 50       170 return( $self->error( "Filehandle provided (", overload::StrVal( $fh ), ") is not a valid filehandle." ) ) if( !$self->_is_glob( $fh ) );
239 22         532 my $opts = $self->_get_args_as_hash( @_ );
240 22         1147 my $reader;
241 22 100       339 if( $reader = $opts->{reader} )
242             {
243 2 50       24 return( $self->error( "Reader object provided (", overload::StrVal( $reader ), ") is not a HTTP::Promise::IO." ) ) if( !$self->_is_a( $reader => 'HTTP::Promise::IO' ) );
244             }
245             else
246             {
247 20   50     160 $reader = HTTP::Promise::IO->new( $fh, max_read_buffer => $self->max_read_buffer, debug => $self->debug ) ||
248             return( $self->pass_error( HTTP::Promise::IO->error ) );
249             }
250             # "It is RECOMMENDED that all HTTP senders and recipients support, at a minimum, request-line lengths of 8000 octets."
251             # Ref: <https://tools.ietf.org/html/rfc7230#section-3.1.1>
252 22         577 my $buff = $reader->getline( max_read_buffer => 8192 );
253             # "A server that receives a method longer than any that it implements SHOULD respond with a 501 (Not Implemented) status code."
254             # Ref: <https://tools.ietf.org/html/rfc7230#section-3.1.1>
255 22 50       74143 return( $self->pass_error( $reader->error ) ) if( !defined( $buff ) );
256 22 50 66     323 unless( $opts->{request} || $opts->{response} )
257             {
258             # Ref: <https://tools.ietf.org/html/rfc7230#section-3.1.2>
259 18 100       1003 if( $buff =~ m,^(${HTTP_VERSION})[[:blank:]]+, )
    100          
260             {
261 2         26 $opts->{response} = 1;
262             }
263             # rfc7230, section 3.1
264             # Ref: <https://tools.ietf.org/html/rfc7230#section-3.1>
265             elsif( $buff =~ m,^(?:CONNECT|DELETE|GET|HEAD|OPTIONS|PATCH|POST|PUT|TRACE)[[:blank:]]+(\S+)[[:blank:]]+${HTTP_VERSION}, )
266             {
267 3         41 $opts->{request} = 1;
268             }
269             # Actually we accept an http message that does not have a first line.
270             # We just won't know what it is for, but it is ok, since we return an entity object
271             # else
272             # {
273             # return( $self->error( "Unknown http message type and no 'request' or 'response' boolean value was provided," ) );
274             # }
275             }
276            
277             # Maximum headers size is not oficial, but we definitely need to set some limit.
278             # <https://security.stackexchange.com/questions/110565/large-over-sizesd-http-header-lengths-and-security-implications>
279 22         185 my $max = $self->max_headers_size;
280 22         801354 my( $n, $def, $headers );
281 22         60 $n = -1;
282 22         141 while( $n != 0 )
283             {
284 25         3349 $n = $reader->read( $buff, 2048, length( $buff ) );
285 25 50       2772 return( $self->pass_error( $reader->error ) ) if( !defined( $n ) );
286 25 100       184 if( $n == 0 )
287             {
288 7 50       19 if( !length( $buff ) )
289             {
290 0         0 return( $self->error({ code => 400, message => "No data could be retrieved from filehandle." }) );
291             }
292             else
293             {
294 7         112 return( $self->error({ code => 425, message => "No headers data could be retrieved in the first " . length( $buff ) . " bytes of data read." }) );
295             }
296             }
297            
298             # If we know the type of http message we are dealing with, we use the fast XS method
299 18 100 100     2734 if( $opts->{request} || $opts->{response} )
300             {
301 9         148 $def = $self->parse_headers_xs( \$buff, $opts );
302             # $def = $self->parse_headers( \$buff, $opts );
303             }
304             # otherwise, we use a more lenient one that does not require a request or response line
305             else
306             {
307 9         488 $def = $self->parse_headers( \$buff, $opts );
308             }
309            
310 18 100       26973 if( !defined( $def ) )
311             {
312             # 400 Bad request
313 4 50 66     19 return( $self->error({ code => 400, message => "Unable to find the headers in the request provided, within the first ${max} bytes of data. Do you need to increase the value for max_headers_size() ?" }) ) if( $self->error->code == 400 && length( $buff ) > $max );
314             # Is it an error 425 Too Early, it means we need more data.
315 4 100       3558 next if( $self->error->code == 425 );
316             # For other errors, we stop and pass the error received
317 1         891 return( $self->pass_error );
318             }
319             else
320             {
321             $headers = $def->{headers} ||
322 14   50     134 return( $self->error( "No headers object set by parse_headers_xs() !" ) );
323 14 50       171 return( $self->error( "parse_headers_xs() did not return the headers length as an integer ($def->{length})" ) ) if( !$self->_is_integer( $def->{length} ) );
324 14 50       340 return( $self->error( "Headers length returned by parse_headers_xs() ($def->{length}) is higher than our buffer size (", length( $buff ), ") !" ) ) if( $def->{length} > length( $buff ) );
325 14         62 substr( $buff, 0, $def->{length}, '' );
326 14 50       193 $reader->unread( $buff ) if( length( $buff ) );
327 14         44 last;
328             }
329             }
330             # We need to consume the blank line separating the headers and the body, so it does
331             # not become part of the body, and because it does not belong anywhere
332 14         473 my $trash = $reader->read_until_in_memory( qr/${CRLF}/, include => 1 );
333            
334 14         2419 my $ent = HTTP::Promise::Entity->new( headers => $headers, debug => $DEBUG );
335 14 50 100     367 if( ( $opts->{request} || $opts->{response} ) && $def->{protocol} )
      66        
336             {
337 9         24 my $message;
338 9 100       36 if( $opts->{request} )
339             {
340 7 50       54 $self->_load_class( 'HTTP::Promise::Request' ) || return( $self->pass_error );
341             $message = HTTP::Promise::Request->new( @$def{qw( method uri headers )}, {
342             protocol => $def->{protocol},
343             version => $def->{version},
344 7   100     1463 debug => $DEBUG
345             } ) ||
346             return( $self->pass_error( HTTP::Promise::Request->error ) );
347             }
348             else
349             {
350 2 50       24 $self->_load_class( 'HTTP::Promise::Response' ) || return( $self->pass_error );
351             $message = HTTP::Promise::Response->new( @$def{qw( code status headers )}, {
352             protocol => $def->{protocol},
353             version => $def->{version},
354 2   50     635 debug => $DEBUG
355             } ) ||
356             return( $self->pass_error( HTTP::Promise::Response->error ) );
357             }
358             # Mutual assignment for convenience
359 8         143 $message->entity( $ent );
360 8         361 $ent->http_message( $message );
361             }
362 13         442 my $type = $ent->mime_type;
363 13         58 my $part_ent;
364             # Request body can be one of 3 types:
365             # application/x-www-form-urlencoded
366             # multipart/form-data
367             # text/plain or other mime types
368             # <https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST>
369 13 100       63 if( $type =~ m,^multipart/,i )
370             {
371 3   50     51 $part_ent = $self->parse_multi_part( entity => $ent, reader => $reader ) ||
372             return( $self->pass_error );
373             # Post process to assign a name to each part, to make it easy to manipulate them
374 3         331 for( $ent->parts->list )
375             {
376 12 100       4396 if( my $dispo = $_->headers->content_disposition )
377             {
378 4         132 my $cd = $_->headers->new_field( 'Content-Disposition' => $dispo );
379 4 50       23 return( $self->pass_error( $_->headers->error ) ) if( !defined( $cd ) );
380 4 50       21 if( my $name = $cd->name )
381             {
382 4         2104 $_->name( $name );
383             }
384             }
385             }
386             }
387             else
388             {
389 10   50     176 $part_ent = $self->parse_singleton( entity => $ent, reader => $reader ) ||
390             return( $self->pass_error );
391             }
392 13         1431 return( $ent );
393             }
394              
395             sub parse_headers($$)
396             {
397 57     57 1 922 my $self = shift( @_ );
398 57         266 my $str = $self->_get_args( shift( @_ ) );
399 57 50       199 return( $self->pass_error ) if( !defined( $str ) );
400 57         339 my $opts = $self->_get_args_as_hash( @_ );
401 57   50     4013 $opts->{convert_dash} //= 0;
402 57   100     423 $opts->{no_headers_ok} //= 0;
403 57 50       193 if( !CORE::length( $$str ) )
404             {
405             return({
406 0         0 length => 0,
407             headers => HTTP::Promise::Headers->new,
408             });
409             }
410            
411             # Basic error catching
412 57 100       972 if( $$str !~ /${CRLF}${CRLF}/ )
413             {
414 7         133 return( $self->error({ code => 425, message => 'Incomplete request, call again when there is more data.', class => $EXCEPTION_CLASS }) );
415             }
416            
417 50         148 my $def = {};
418 50         205 pos( $$str ) = 0;
419 50 100       1950 if( $$str =~ m,^(${HTTP_VERSION})[[:blank:]]+(?<code>\d{3})[[:blank:]]+(?<status>.*?)$CRLF,gc )
    100          
    100          
    100          
420             {
421 9         119 @$def{qw( protocol code status )} = @+{qw( http_protocol code status )};
422 9         105 $def->{version} = version->parse( $+{http_version} );
423             }
424             # rfc7230, section 3.1
425             # Ref: <https://tools.ietf.org/html/rfc7230#section-3.1>
426             # CONNECT, DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT, TRACE
427             # But there could be others including non-standard ones
428             elsif( $$str =~ m|^(?<method>[A-Z]{3,12})[[:blank:]]+(?<uri>\S+)[[:blank:]]+(${HTTP_VERSION})$CRLF|gc )
429             {
430 9         311 @$def{qw( method uri protocol )} = @+{qw( method uri http_protocol )};
431 9         222 $def->{version} = version->parse( $+{http_version} );
432             }
433             # HTTP/0.9 "Simple Request"
434             # See rfc1945, section 5
435             # <https://tools.ietf.org/html/rfc1945#page-23>
436             elsif( $$str =~ m|^(GET)[[:blank:]]+(\S+)[[:blank:]]*$CRLF|gc )
437             {
438 2         32 @$def{qw( method uri )} = ( $1, $2 );
439 2         16 $def->{protocol} = 'HTTP/0.9';
440 2         47 $def->{version} = version->parse( '0.9' );
441             # There should not be any header in a simple request
442 2 50       121 return( $self->error({ code => 400, message => 'Bad request', class => $EXCEPTION_CLASS }) ) if( $$str =~ /^$HEADER/ );
443 2         10 $def->{length} = pos( $$str );
444 2         37 $def->{headers} = HTTP::Promise::Headers->new;
445 2         13 return( $def );
446             }
447             elsif( $$str =~ /^(?:[A-Z]+\/\d+\.\d+|[A-Z]+[[:blank:]\h]+(?!\:))/ )
448             {
449 5 100       41 my $type = $$str =~ m,^[A-Z]+\/\d+\.\d+, ? 'Response' : 'Request';
450 5         43 return( $self->error({ code => 400, message => "Bad ${type}-Line", class => $EXCEPTION_CLASS }) );
451             }
452              
453 43 100 100     1296 if( pos( $$str ) == 0 && $$str !~ /^$HEADER/ )
454             {
455 4         80 return( $self->error({ code => 400, message => 'Bad request', class => $EXCEPTION_CLASS }) );
456             }
457              
458 39         258 my $headers = $self->new_array;
459            
460 39         1021 my $len = 0;
461             # my $remain = CORE::length( $$str );
462             # while( $$str =~ s/^$HEADER// )
463 39         905 while( $$str =~ /\G$HEADER/gc )
464             {
465             # $len += ( $remain - CORE::length( $$str ) );
466             # $remain = CORE::length( $$str );
467 59         964 my( $n, $v ) = ( lc( $1 ), $2 );
468 59 50       207 $n =~ tr/-/_/ if( $opts->{convert_dash} );
469 59         257 $headers->push( $n => $v );
470             }
471 39         475 $len = pos( $$str );
472            
473 39 100       407 unless( $$str =~ /\G${CRLF}/gc )
474             {
475 2 100       15 my $type = $def->{code} ? 'response' : 'request';
476 2         45 return( $self->error({ code => 400, message => "Bad ${type}", class => $EXCEPTION_CLASS }) );
477             }
478              
479 37         161 foreach( @$headers )
480             {
481 118         1180 s/$LWS+/\x20/g;
482 118         506 s/^$LWS//;
483 118         570 s/$LWS$//;
484             }
485             # return( want( 'LIST' ) ? $headers->list : $headers );
486 37         195 $def->{length} = $len;
487 37         613 $def->{headers} = HTTP::Promise::Headers->new( @$headers );
488 37         238 return( $def );
489             }
490              
491             sub parse_headers_xs($$)
492             {
493 10     10 1 47 my $self = shift( @_ );
494 10   50     140 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
495 10         70 my $opts = $self->_get_args_as_hash( @_ );
496 10 50 66     2022 if( ( !exists( $opts->{request} ) && !exists( $opts->{response} ) ) ||
      66        
      66        
497             ( !length( $opts->{request} ) && !length( $opts->{response} ) ) )
498             {
499 0         0 return( $self->error({ code => 500, message => "Missing 'request' or 'response' property to ste how to parse the http headers.", class => $EXCEPTION_CLASS }) );
500             }
501 10   50     77 my $max_headers_size = $self->max_headers_size // 0;
502            
503 10         43590 my $r = {};
504 10         45 my $len;
505             my $bkp_version;
506             # try-catch
507 10         37 local $@;
508             eval
509 10         44 {
510 10 100       68 if( $opts->{request} )
    50          
511             {
512             # We have to do this, because of a bug in TTP::Parser2::XS where HTTP/2 is not supported.
513             # We save the value and replace it with one supported and we put it back after in
514             # the data we return.
515             # <https://rt.cpan.org/Ticket/Display.html?id=142808>
516 8 50       56 if( index( $$str, 'HTTP/2' ) != -1 )
517             {
518 0 0       0 if( $$str =~ s,^((?:\S+)[[:blank:]\h]+(?:\S+)[[:blank:]\h]+HTTP/)(2(?:\.\d)?),${1}1.1, )
519             {
520 0         0 $bkp_version = $2;
521             }
522             }
523 8         391 $len = HTTP::Parser2::XS::parse_http_request( $$str, $r );
524             }
525             elsif( $opts->{response} )
526             {
527 2 50       21 if( index( $$str, 'HTTP/2' ) != -1 )
528             {
529 0 0       0 if( $$str =~ s,^(HTTP/)(2(?:\.\d)?),${1}1.1, )
530             {
531 0         0 $bkp_version = $2;
532             }
533             }
534 2         90 $len = HTTP::Parser2::XS::parse_http_response( $$str, $r );
535             }
536             };
537 10 50       83 if( $@ )
538             {
539 0         0 return( $self->error({ code => 400, message => $@, class => $EXCEPTION_CLASS }) );
540             }
541            
542 10 50 33     165 if( $len == -1 )
    50 33        
    50          
543             {
544 0         0 return( $self->error({ code => 400, message => 'Bad request', class => $EXCEPTION_CLASS }) );
545             }
546             elsif( $len == -2 && $max_headers_size > 0 && length( $$str ) > $max_headers_size )
547             {
548             # 431: HTTP request header fields too large
549             # 413: Request entity too large
550 0         0 return( $self->error({ code => 413, message => 'Incomplete and too long request', class => $EXCEPTION_CLASS }) );
551             }
552             # Which one is best?
553             # 406 Unacceptable
554             # 411 Length required
555             # 417 Expectation failed
556             # 422 Unprocessable entity
557             # 425 Too early
558             elsif( $len == -2 )
559             {
560 0         0 return( $self->error({ code => 425, message => 'Incomplete request, call again when there is more data.', class => $EXCEPTION_CLASS }) );
561             }
562             # response headers:
563             # {
564             # "_content_length" => 15,
565             # "_keepalive" => 0,
566             # "_message" => "OK",
567             # "_protocol" => "HTTP/1.0",
568             # "_status" => 200,
569             # "content-length" => [15],
570             # "content-type" => ["text/plain"],
571             # "host" => ["example.com"],
572             # "user-agent" => ["hoge"],
573             # }
574             # request headers:
575             # {
576             # "_content_length" => 27,
577             # "_keepalive" => 1,
578             # "_method" => "POST",
579             # "_protocol" => "HTTP/1.1",
580             # "_query_string" => "",
581             # "_request_uri" => "/test",
582             # "_uri" => "/test",
583             # "content-length" => [27],
584             # "content-type" => ["application/x-www-form-urlencoded"],
585             # "host" => ["foo.example"],
586             # }
587 10 50       44 $r->{_protocol} = "HTTP/${bkp_version}" if( defined( $bkp_version ) );
588             # warn( "HTTP::Parser2::XS->parse_headers_xs: bytes read ($len) differs from _content_length (", ( $r->{_content_length} // '' ), ")\n" ) if( defined( $r->{_content_length} ) && length( $r->{_content_length} ) && $len != $r->{_content_length} && $self->_warnings_is_enabled );
589 10         56 my $def = { length => $len };
590             # Sadly enough, HTTP::Parser2::XS does not provide the order of the header and
591             # although we could find out ourself, it would defeat the purpose of using an XS module
592             # so we default to alphabetical order
593             # If this is really important, you can use parse_request method instead
594 10         64 my $headers = $self->new_array;
595             # Skip keys that start with _. They are private properties
596 10         471 for( sort( grep( !/^_/, keys( %$r ) ) ) )
597             {
598 39         217 my $k = $_;
599 39 50       88 $k =~ tr/-/_/ if( $opts->{convert_dash} );
600 39         112 $headers->push( $k => $r->{ $_ } );
601             }
602 10         456 $def->{headers} = HTTP::Promise::Headers->new( @$headers );
603 10 100       111 if( $opts->{request} )
    50          
604             {
605 8         86 @$def{qw( method protocol )} = @$r{qw( _method _protocol )};
606 8 50 33     232 $def->{uri} = URI->new( $r->{_request_uri} ) if( exists( $r->{_request_uri} ) && length( $r->{_request_uri} ) );
607             }
608             elsif( $opts->{response} )
609             {
610 2         25 @$def{qw( code status protocol )} = @$r{qw( _status _message _protocol )};
611             }
612 10   50     1061 $def->{version} = $self->parse_version( $r->{_protocol} ) || return( $self->pass_error );
613             # It seems
614 10         1193 while( substr( $$str, 0, $len ) =~ /$CRLF($CRLF)$/ )
615             {
616 10         111 $len -= length( $1 );
617             }
618 10         47 $def->{length} = $len;
619 10         61 return( $def );
620             }
621              
622             sub parse_multi_part
623             {
624 4     4 1 21 my $self = shift( @_ );
625 4         25 my $opts = $self->_get_args_as_hash( @_ );
626             my $ent = $opts->{entity} ||
627 4   50     694 return( $self->error({ code => 500, message => "No entity object was provided." }) );
628             my $reader = $opts->{reader} ||
629 4   50     25 return( $self->error({ code => 500, message => "No reader object was provided." }) );
630 4   50     19 my $headers = $ent->headers ||
631             return( $self->error({ code => 500, message => "No headers object found in entity object." }) );
632 4         122 my $ct = $headers->content_type;
633 4   50     81 my $h = $headers->new_field( 'Content-Type' => $ct ) || return( $self->pass_error( $headers->error ) );
634 4   50     18 my $boundary = $h->boundary ||
635             return( $self->error( "No boundary could be found in the Content-Type header '$ct'" ) );
636 4         2180 my $max_in_memory = $self->max_body_in_memory_size;
637 4   50     110111 my $default_mime = $DEFAULT_MIME_TYPE || 'application/octet-stream';
638            
639             # Position ourself right after the first boundary, including the trailing CRLF sequence
640 4         162 my $trash = $reader->read_until_in_memory( qr/--${boundary}${CRLF}/, include => 1, capture => 1 );
641 4 50       590 return( $self->pass_error( $reader->error ) ) if( !defined( $trash ) );
642 4 50       29 return( $self->error( "Unable to find the initial boundary '${boundary}'" ) ) if( !length( $trash ) );
643 4         19 my $delim = $reader->last_delimiter;
644 4         3191 my $preamble;
645 4 50       16 if( length( $delim ) )
646             {
647 4         42 $preamble = substr( $trash, 0, index( $trash, $delim ) );
648 4         74 $self->_trim_crlf( \$preamble );
649 4 100       57 $ent->preamble( [split( /$CRLF/, $preamble )] ) if( length( $preamble ) );
650             }
651            
652 4         1462 my( $buff, $mime, $def );
653 4         9 while(1)
654             {
655             # I expect an header token and value, but if we find a CRLF sequence right now,
656             # this just means there is no header.
657 14         507 my $hdr = $reader->read_until_in_memory( qr/(?:^${CRLF}|(?:(?:$TOKEN+)[\x09\x20]*\:(?:.+?)${CRLF}${CRLF}))/, include => 1 );
658 14 50       2099 return( $self->pass_error( $reader->error ) ) if( !defined( $hdr ) );
659 14 50       68 last if( !length( $hdr ) );
660 14         53 my( $ph, $file, $mime_type, $ext, $io );
661 14 100 66     308 if( length( $hdr ) && $hdr !~ /^$CRLF$/ )
662             {
663 10   50     123 $def = $self->parse_headers( $hdr ) || return( $self->pass_error );
664 10         279 $ph = $def->{headers};
665 10         99 my $dispo = $ph->new_field( 'Content-Disposition' => $ph->content_disposition );
666             # rfc7231, section 3.1.1.5 says we can assume applicatin/octet-stream if there
667             # is no Content-Type header
668             # <https://tools.ietf.org/html/rfc7231#section-3.1.1.5>
669 10         95 $mime_type = $ph->mime_type( $default_mime );
670             }
671             # If no headers are set, we create a dummy object
672             else
673             {
674 4 50       79 $reader->unread( $hdr ) if( $hdr =~ /^$CRLF$/ );
675 4         118 $ph = HTTP::Promise::Headers->new;
676             }
677 14   50     130 my $part_ent = HTTP::Promise::Entity->new( headers => $ph, debug => $self->debug ) ||
678             return( $self->pass_error( HTTP::Promise::Entity->error ) );
679 14 100 100     208 if( defined( $mime_type ) && $mime_type eq 'multipart/form-data' )
680             {
681             # $sub_part_ent and $part_ent should be the same
682 1   50     21 my $sub_part_ent = $self->parse_multi_part( entity => $part_ent, reader => $reader ) ||
683             return( $self->pass_error );
684             # We need to consume the boundary for this part
685             # Position ourself just before the next delimiter, but do not include it.
686             # That way, we can capture epilogue data, if any, and although rare in HTTP parlance.
687 1         265 my $trash = $reader->read_until_in_memory( qr/${CRLF}--${boundary}(?:\-{2})?${CRLF}/, include => 1, capture => 1 );
688 1         160 my $delim = $reader->last_delimiter;
689 1         912 my $epilogue;
690 1 50       10 if( length( $delim ) )
691             {
692 1         37 $epilogue = substr( $trash, 0, index( $trash, $delim ) );
693 1         45 $self->_trim_crlf( \$epilogue );
694 1 50       35 $ent->epilogue( [split( /$CRLF/, $epilogue )] ) if( length( $epilogue ) );
695             }
696             # Post process to assign a name to each part, to make it easy to manipulate them
697 1         791 for( $part_ent->parts->list )
698             {
699 2 50       1491 if( my $dispo = $_->headers->content_disposition )
700             {
701 2         80 my $cd = $_->headers->new_field( 'Content-Disposition' => $dispo );
702 2 50       18 return( $self->pass_error( $_->headers->error ) ) if( !defined( $cd ) );
703 2 50       14 if( my $name = $cd->name )
704             {
705 2         1125 $_->name( $name );
706             }
707             }
708             }
709             }
710             # Otherwise, we are dealing with a simple part
711             else
712             {
713 13   50     473 my $sub_part_ent = $self->parse_singleton(
714             entity => $part_ent,
715             reader => $reader,
716             read_until => qr/${CRLF}--${boundary}(?:\-{2})?${CRLF}/,
717             ) || return( $self->pass_error );
718             }
719 14         2198 $ent->parts->push( $part_ent );
720             # Have we reached the last delimiter yet?
721 14         9237 my $last = $reader->last_delimiter;
722             # We hit the ending delimiter, stop here.
723             # If there are any epilogue, they will be dealt with by our caller
724 14 100       12908 last if( $last =~ /\-\-${boundary}\-\-${CRLF}$/ );
725             }
726 4         145 return( $ent );
727             }
728              
729             sub parse_open
730             {
731 0     0 1 0 my $self = shift( @_ );
732 0   0     0 my $expr = shift( @_ ) ||
733             return( $self->error( "No file to open was provided." ) );
734 0         0 my $ent;
735 0   0     0 my $f = $self->new_file( $expr ) ||
736             return( $self->pass_error );
737 0   0     0 my $io = $f->open ||
738             return( $self->pass_error( $f->error ) );
739 0   0     0 $ent = $self->parse( $io ) ||
740             return( $self->pass_error );
741 0 0       0 $io->close or return( $self->pass_error( $io->error ) );
742 0         0 return( $ent );
743             }
744              
745             sub parse_request($$)
746             {
747 0     0 1 0 my $self = shift( @_ );
748 0   0     0 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
749 0         0 my $opts = $self->_get_args_as_hash( @_ );
750 0   0     0 my $req = $self->parse_request_headers( $str, $opts ) || return( $self->pass_error );
751 0         0 substr( $$str, 0, $req->{length}, '' );
752 0         0 $req->{content} = $str;
753 0         0 return( $req );
754             }
755              
756             sub parse_request_headers($$)
757             {
758 1     1 1 50 my $self = shift( @_ );
759 1   50     16 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
760 1         16 my $opts = $self->_get_args_as_hash( @_ );
761 1         19 $opts->{request} = 1;
762 1         29 return( $self->parse_headers_xs( $str, $opts ) );
763             }
764              
765             sub parse_request_line($$)
766             {
767 0     0 1 0 my $self = shift( @_ );
768 0   0     0 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
769 0         0 my $len = CORE::length( $$str );
770 0 0       0 $$str =~ s/^$REQUEST// or return( $self->error({ code => 400, message => 'Bad request-line', class => $EXCEPTION_CLASS }) );
771 0   0     0 my $res =
772             {
773             method => $1,
774             path => $2,
775             protocol => ( $3 || 'HTTP/0.9' ),
776             length => ( $len - CORE::length( $$str ) ),
777             };
778 0         0 $res->{version} = $self->parse_version( $res->{protocol} );
779 0         0 return( $res );
780             }
781              
782             sub parse_request_pp($$)
783             {
784 19     19 1 81708 my $self = shift( @_ );
785 19   50     211 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
786 19   100     150 my $req = $self->parse_headers( $str, @_ ) || return( $self->pass_error );
787 10         265 substr( $$str, 0, $req->{length}, '' );
788 10 100       158 $$str =~ s/^$CRLF// or return( $self->error({ code => 400, message => 'Bad request', class => $EXCEPTION_CLASS }) );
789 9 100       581 if( $req->{version} < version->parse( '1.0' ) )
790             {
791 1 50       13 $$str eq '' or return( $self->error({ code => 400, message => 'Bad request', class => $EXCEPTION_CLASS }) );
792             }
793 9         91 $req->{content} = $str;
794 9         43 return( $req );
795             }
796              
797             sub parse_response($$)
798             {
799 0     0 1 0 my $self = shift( @_ );
800 0   0     0 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
801 0         0 my $opts = $self->_get_args_as_hash( @_ );
802 0   0     0 my $resp = $self->parse_response_headers( $str, $opts ) || return( $self->pass_error );
803 0         0 substr( $$str, 0, $resp->{length}, '' );
804 0         0 $resp->{content} = $str;
805 0         0 return( $resp );
806             }
807              
808             sub parse_response_headers($$)
809             {
810 0     0 1 0 my $self = shift( @_ );
811 0   0     0 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
812 0         0 my $opts = $self->_get_args_as_hash( @_ );
813 0         0 $opts->{response} = 1;
814 0         0 return( $self->parse_headers_xs( $str, $opts ) );
815             }
816              
817             sub parse_response_line($$)
818             {
819 0     0 1 0 my $self = shift( @_ );
820 0   0     0 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
821 0         0 my $len = CORE::length( $$str );
822 0 0       0 $$str =~ s/^$RESPONSE// or return( $self->error({ code => 400, message => 'Bad Status-Line', class => $EXCEPTION_CLASS }) );
823 0         0 my $res =
824             {
825             protocol => $1,
826             code => $2,
827             status => $3,
828             length => ( $len - CORE::length( $$str ) ),
829             };
830 0         0 $res->{version} = $self->parse_version( $res->{protocol} );
831 0         0 return( $res );
832             }
833              
834             sub parse_response_pp($$)
835             {
836 13     13 1 56404 my $self = shift( @_ );
837 13   50     45 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
838 13         50 my $opts = $self->_get_args_as_hash( @_ );
839 13         68 $opts->{no_headers_ok} = 1;
840 13   100     36 my $resp = $self->parse_headers( $str, $opts ) || return( $self->pass_error );
841 8         164 substr( $$str, 0, $resp->{length}, '' );
842 8 50       87 $$str =~ s/^$CRLF// or return( $self->error({ code => 400, message => 'Bad response', class => $EXCEPTION_CLASS }) );
843 8         19 $resp->{content} = $str;
844 8         30 return( $resp );
845             }
846              
847             # Called when there is no multipart
848             sub parse_singleton
849             {
850 23     23 1 106 my $self = shift( @_ );
851 23         131 my $opts = $self->_get_args_as_hash( @_ );
852             my $ent = $opts->{entity} ||
853 23   50     4305 return( $self->error({ code => 500, message => "No entity object was provided." }) );
854             my $reader = $opts->{reader} ||
855 23   50     120 return( $self->error({ code => 500, message => "No reader object was provided." }) );
856 23   50     92 my $headers = $ent->headers ||
857             return( $self->error({ code => 500, message => "No headers object found in entity object." }) );
858 23         813 my $type = $headers->type;
859 23         132 my $read_until = $opts->{read_until};
860 23         351 my $max_in_memory = $self->max_body_in_memory_size;
861             # rfc7231, section 3.1.1.5 says we can assume applicatin/octet-stream if there
862             # is no Content-Type header
863             # <https://tools.ietf.org/html/rfc7231#section-3.1.1.5>
864 23   50     375921 my $default_mime = $DEFAULT_MIME_TYPE || 'application/octet-stream';
865 23         181 my $len = $headers->content_length;
866 23         35830 my $chunk_size = 2048;
867 23         69 my( $body, $file, $mime_type, $mime, $ext );
868 23         95 my $data = '';
869 23         56 my $total_bytes = 0;
870            
871             my $get_temp_file = sub
872             {
873             # Guessing extension
874 0     0   0 $mime_type = $headers->mime_type( $default_mime );
875 0 0       0 $self->_load_class( 'HTTP::Promise::MIME' ) || return( $self->pass_error );
876 0         0 $mime = HTTP::Promise::MIME->new;
877 0         0 $ext = $mime->suffix( $type );
878 0 0       0 return( $self->pass_error( $mime->error ) ) if( !defined( $ext ) );
879 0   0     0 $ext ||= 'dat';
880 0   0     0 my $f = $self->new_tempfile( extension => $ext ) ||
881             return( $self->pass_error );
882 0         0 return( $f );
883 23         285 };
884            
885 23 100 66     152 if( defined( $len ) && !defined( $read_until ) )
886             {
887             # Nothing to be done. The body is zero byte, like in HEAD request
888 1 50       8 if( !$len )
    50          
889             {
890             #
891             }
892             # Too big, saving it to file
893             elsif( $len > $max_in_memory )
894             {
895             # We cannot save this to file if the type is application/x-www-form-urlencoded
896 0 0 0     0 if( $type eq TYPE_URL_ENCODED && $self->decode_body )
897             {
898             # Payload too large
899 0         0 return( $self->error({ code => 413, message => "The data are url-encoded, but its total amount (${len}) exceeds the maximum allowed ($max_in_memory}). You may want to increase that limit or investigate this HTTP message." }) );
900             }
901 0   0     0 $file = $get_temp_file->() || return( $self->pass_error );
902 0   0     0 my $io = $file->open( '+>', { binmode => 'raw', autoflush => 1 } ) ||
903             return( $self->pass_error( $file->error ) );
904 0         0 my $buff = '';
905 0         0 my $bytes;
906 0 0       0 $chunk_size = $len if( $chunk_size > $len );
907 0         0 while( $bytes = $reader->read( $buff, $chunk_size ) )
908             {
909 0 0       0 $io->print( $buff ) || return( $self->pass_error( $io->error ) );
910             # We do not want to read more than we should
911 0 0       0 $chunk_size = ( $len - $total_bytes ) if( $total_bytes + $chunk_size > $len );
912 0         0 $total_bytes += $bytes;
913 0 0       0 last if( $total_bytes == $len );
914             }
915 0         0 $io->close;
916 0 0       0 return( $self->error( "Error reading http body from filehandle: ", $reader->error ) ) if( !defined( $bytes ) );
917             }
918             else
919             {
920 1         241 my $bytes = $reader->read( $data, $len );
921 1 50       143 return( $self->error( "Error reading HTTP body from filehandle: ", $reader->error ) ) if( !defined( $bytes ) );
922             # Assignment used for the warning below
923 1         2 $total_bytes = $bytes;
924             }
925 1 50 33     9 warn( ref( $self ), "->parse_singleton: Warning only: HTTP body size advertised ($len) does not match the size actually read from filehandle ($total_bytes)\n" ) if( $total_bytes != $len && warnings::enabled( ref( $self ) ) );
926             }
927             # No Content-Length defined or there is a boundary expected
928             else
929             {
930 22         114 my $buff = '';
931 22         73 my $bytes = -1;
932 22         53 my $io;
933 22         95 while( $bytes )
934             {
935 25 100       415 if( defined( $read_until ) )
936             {
937 13         163 $bytes = $reader->read_until( $buff, $chunk_size, { string => $read_until, ignore => 1, capture => 1 } );
938             }
939             else
940             {
941 12         78 $bytes = $reader->read( $buff, $chunk_size );
942             }
943 25 50       872 return( $self->pass_error( $reader->error ) ) if( !defined( $bytes ) );
944            
945 25 50       208 if( defined( $io ) )
    50          
946             {
947 0 0       0 $io->print( $buff ) || return( $self->pass_error( $io->error ) );
948             }
949             # The cumulative bytes total for this part exceeds the allowed maximum in memory
950             elsif( ( length( $data ) + length( $buff ) ) > $max_in_memory )
951             {
952 0 0 0     0 if( $type eq TYPE_URL_ENCODED && $self->decode_body )
953             {
954             # Payload too large
955 0         0 return( $self->error({ code => 413, message => sprintf( "The data are url-encoded, but its total amount so far (%d) is about to exceed the maximum allowed ($max_in_memory}). You may want to increase that limit or investigate this HTTP message.",length( $data ) ) }) );
956             }
957 0   0     0 $file = $get_temp_file->() || return( $self->pass_error );
958 0   0     0 $io = $file->open( '+>', { binmode => 'raw', autoflush => 1 } ) ||
959             return( $self->pass_error( $file->error ) );
960 0 0       0 $io->print( $data ) || return( $self->pass_error( $io->error ) );
961 0         0 $data = '';
962             }
963             else
964             {
965 25         3784 $data .= $buff;
966             }
967             # reader returns negative bytes if those are the last bytes read until it reached the boundary
968 25 100       217 last if( $bytes < 0 );
969             }
970 22 50       148 $total_bytes = defined( $file ) ? $file->length : length( $data );
971             }
972            
973              
974             # If we used a file and the extension is 'dat', because we were clueless based on
975             # the provided Content-Type, or maybe even the Content-Type is absent, we use the
976             # XS module in HTTP::Promise::MIME to guess the mime-type based on the actual file
977             # content
978 23 50       272 if( defined( $file ) )
979             {
980 0 0 0     0 if( defined( $file ) && $mime_type eq $default_mime )
981             {
982 0 0       0 unless( $mime )
983             {
984 0 0       0 $self->_load_class( 'HTTP::Promise::MIME' ) || return( $self->pass_error );
985 0         0 $mime = HTTP::Promise::MIME->new;
986             }
987            
988             # Guess the mime type from the file magic
989 0         0 my $mtype = $mime->mime_type( $file );
990 0 0       0 return( $self->pass_error( $mime->error ) ) if( !defined( $mime_type ) );
991 0 0 0     0 if( $mtype && $mtype ne $default_mime )
992             {
993 0         0 $mime_type = $mtype;
994             # Also update the type value in HTTP::Promise::Headers
995             # It does not affect the actual Content-Type header
996 0         0 $headers->type( $mtype );
997 0         0 my $new_ext = $mime->suffix( $mtype );
998 0 0       0 return( $self->pass_error( $mime->error ) ) if( !defined( $new_ext ) );
999 0 0 0     0 if( $new_ext && $new_ext ne $ext )
1000             {
1001 0   0     0 my $new_file = $file->extension( $ext ) || return( $self->pass_error( $file->error ) );
1002 0   0     0 my $this_file = $file->move( $new_file ) || return( $self->pass_error( $file->error ) );
1003 0         0 $file = $this_file;
1004             }
1005             }
1006             }
1007            
1008 0   0     0 $body = $ent->new_body( file => $file ) ||
1009             return( $self->pass_error( $ent->error ) );
1010             }
1011             # in memory
1012             else
1013             {
1014             # If this is a application/x-www-form-urlencoded type, we save it as such, and
1015             # the HTTP::Promise::Body::Form makes those data accessible as an hash object
1016 23 100 100     288 if( defined( $type ) && $type eq TYPE_URL_ENCODED )
1017             {
1018 1   50     27 $body = $ent->new_body( form => $data ) ||
1019             return( $self->pass_error( $ent->error ) );
1020             }
1021             else
1022             {
1023 22   50     312 $body = $ent->new_body( string => $data ) ||
1024             return( $self->pass_error( $ent->error ) );
1025             }
1026             }
1027 23         217 $ent->body( $body );
1028 23         1694 my $enc = $headers->content_encoding;
1029 23 50 66     206 if( $enc && $body->length && $self->decode_body( $enc ) )
      66        
1030             {
1031 4 50       3168 $ent->decode_body( $enc ) || return( $self->pass_error( $ent->error ) );
1032 4         67 $ent->is_encoded(0);
1033             }
1034 23         3636 return( $ent );
1035             }
1036              
1037             sub parse_version($$)
1038             {
1039 10     10 1 35 my $self = shift( @_ );
1040 10         29 my $str = shift( @_ );
1041 10 50 33     153 return( $self->error({ code => 400, message => "No data was provided to parse the http version", class => $EXCEPTION_CLASS }) ) if( !defined( $str ) || !length( $str ) );
1042 10 50       511 $str =~ m/^${HTTP_VERSION}$/ or
1043             return( $self->error({ code => 400, message => "Bad HTTP-Version '$str'", class => $EXCEPTION_CLASS }) );
1044 10         198 my $major = $+{http_vers_major};
1045             # May be undef if HTTP/2 for example
1046 10         67 my $minor = $+{http_vers_minor};
1047 10         231 my $v = version->parse( $+{http_version} );
1048 10 50       78 return( want( 'LIST' ) ? ( $major, $minor ) : $v );
1049             }
1050              
1051 0     0 1 0 sub tmp_dir { return( shift->_set_get_file( 'tmp_dir', @_ ) ); }
1052              
1053 0     0 1 0 sub tmp_to_core { return( shift->_set_get_boolean( 'tmp_to_core', @_ ) ); }
1054              
1055             sub _get_args
1056             {
1057 100     100   313 my $self = shift( @_ );
1058 100         179 my $str = shift( @_ );
1059 100 100       514 if( !ref( $str ) )
    50          
1060             {
1061 16         68 $str = \"$str";
1062             }
1063             elsif( !$self->_is_scalar( $str ) )
1064             {
1065 0         0 return( $self->error({ code => 401, message => "Value provided (" . overload::StrVal( $str ) . ") is not a string", class => $EXCEPTION_CLASS }) );
1066             }
1067 100         1051 return( $str );
1068             }
1069              
1070             sub _trim_crlf
1071             {
1072 5     5   21 my $self = shift( @_ );
1073 5         13 my $ref = shift( @_ );
1074 5 50       19 return( $ref ) if( !defined( $ref ) );
1075 5 50       29 die( "Bad argument. This must be provided a scalar reference.\n" ) if( !$self->_is_scalar( $ref ) );
1076 5         58 my $n = 0;
1077 5   66     72 substr( $$ref, $n, 1, '' ), $n++ while( substr( $$ref, $n, 1 ) eq "\015" || substr( $$ref, $n, 1 ) eq "\012" );
1078 5         15 $n = length( $$ref );
1079 5   66     92 $n-- while( substr( $$ref, ($n - 1), 1 ) eq "\015" || substr( $$ref, ($n - 1), 1 ) eq "\012" );
1080 5         23 substr( $$ref, $n, length( $$ref ), '' );
1081 5         11 return( $ref );
1082             }
1083              
1084             # NOTE: sub FREEZE is inherited
1085              
1086 1     1 0 188 sub STORABLE_freeze { CORE::return( CORE::shift->FREEZE( @_ ) ); }
1087              
1088 1     1 0 7445 sub STORABLE_thaw { CORE::return( CORE::shift->THAW( @_ ) ); }
1089              
1090             # NOTE: sub THAW is inherited
1091              
1092             1;
1093             # NOTE: POD
1094             __END__
1095              
1096             =encoding utf-8
1097              
1098             =head1 NAME
1099              
1100             HTTP::Promise::Parser - Fast HTTP Request & Response Parser
1101              
1102             =head1 SYNOPSIS
1103              
1104             use HTTP::Promise::Parser;
1105             my $p = HTTP::Promise::Parser->new ||
1106             die( HTTP::Promise::Parser->error, "\n" );
1107             my $ent = $p->parse( '/some/where/http_request.txt' ) ||
1108             die( $p->error );
1109             my $ent = $p->parse( $file_handle ) ||
1110             die( $p->error );
1111             my $ent = $p->parse( $string ) ||
1112             die( $p->error );
1113              
1114             =head1 VERSION
1115              
1116             v0.2.0
1117              
1118             =head1 DESCRIPTION
1119              
1120             This is an http request and response parser using XS modules whenever posible for speed and mindful of memory consumption.
1121              
1122             As rfc7230 states in its L<section 3|https://tools.ietf.org/html/rfc7230#section-3>:
1123              
1124             "The normal procedure for parsing an HTTP message is to read the start-line into a structure, read each header field into a hash table by field name until the empty line, and then use the parsed data to determine if a message body is expected. If a message body has been indicated, then it is read as a stream until an amount of octets equal to the message body length is read or the connection is closed."
1125              
1126             Thus, L<HTTP::Promise> approach is to read the data, whether a HTTP request or response, a.k.a, an HTTP message, from a filehandle, possibly L<chunked|https://tools.ietf.org/html/rfc7230#section-4.1>, and to first read the message L<headers|HTTP::Promise::Headers> and parse them, then to store the HTTP message in memory if it is under a specified threshold, or in a file. If the size is unknown, it would be first read in memory and switched automatically to a file when it reaches the threshold.
1127              
1128             Once the overall message body is stored, if it is a multipart type, L<this class|HTTP::Promise::Parser> reads each of its parts into memory or separate file depending on its size until there is no more part, using the L<stream reader|HTTP::Promise::IO>, which reads in chunks of bytes and not in lines. If the message body is a single part it is saved to memory or file depending on its size. Each part saved on file uses a file extension related to its L<mime type|HTTP::Promise::MIME>. Each of the parts are then accessible as a L<HTTP body object|HTTP::Promise::Body> via the L<HTTP::Promise::Entity/parts> method.
1129              
1130             Note, however, that when dealing with multipart, this only recognises C<multipart/form-data>, anything else will be treated as data.
1131              
1132             The overall HTTP message is available as an L<HTTP::Promise::Entity> object and returned.
1133              
1134             If an error occurs, this module does not die, at least not voluntarily, but instead sets an L<error|Module::Generic/error> and returns C<undef>, so always make sure to check the returned value from method calls.
1135              
1136             =head1 CONSTRUCTOR
1137              
1138             =head2 new
1139              
1140             This instantiates a new L<HTTP::Promise::Parser> object.
1141              
1142             It takes the following options:
1143              
1144             =over 4
1145              
1146             =item * C<decode_body>
1147              
1148             Boolean. If enabled, this will have this interface automatically decode the entity body upon parsing. Default is true.
1149              
1150             =item * C<decode_headers>
1151              
1152             Boolean. If enabled, this will decode headers, which is used for decoding filename value in C<Content-Encoding>. Default is false.
1153              
1154             =item * C<ignore_filename>
1155              
1156             Boolean. Wether the filename provided in an C<Content-Disposition> should be ignored or not. This defaults to false, but actually, this is not used and the filename specified in a C<Content-Disposition> header field is never used. So, this is a no-op and should be removed.
1157              
1158             =item * C<max_body_in_memory_size>
1159              
1160             Integer. This is the threshold beyond which an entity body that is initially loaded into memory will switched to be loaded into a file on the local filesystem when it is a true value and exceeds the amount specified.
1161              
1162             By defaults, this has the value set by the class variable C<$MAX_BODY_IN_MEMORY_SIZE>, which is 102400 bytes or 100K
1163              
1164             =item * C<max_headers_size>
1165              
1166             Integer. This is the threshold size in bytes beyond which HTTP headers will trigger an error. This defaults to the class variable C<$MAX_HEADERS_SIZE>, which itself is set by default to 8192 bytes or 8K
1167              
1168             =item * C<max_read_buffer>
1169              
1170             Integer. This is the read buffer size. This is used for L<HTTP::Promise::IO> and this defaults to 2048 bytes (2Kb).
1171              
1172             =item * C<output_dir>
1173              
1174             Filepath of the directory to be used to save entity body, when applicable.
1175              
1176             =item * C<tmp_dir>
1177              
1178             Set the directory to use when creating temporary files.
1179              
1180             =item * C<tmp_to_core>
1181              
1182             Boolean. When true, this will set the temporary file to an in-memory space.
1183              
1184             =back
1185              
1186             =head1 METHODS
1187              
1188             =head2 decode_body
1189              
1190             Boolean. If enabled, this will have this interface automatically decode the entity body upon parsing. Default is true.
1191              
1192             =head2 decode_headers
1193              
1194             Boolean. If enabled, this will decode headers, which is used for decoding filename value in C<Content-Encoding>. Default is false.
1195              
1196             =head2 ignore_filename
1197              
1198             Boolean. Wether the filename provided in an C<Content-Disposition> should be ignored or not. This defaults to false, but actually, this is not used and the filename specified in a C<Content-Disposition> header field is never used. So, this is a no-op and should be removed.
1199              
1200             =head2 looks_like_request
1201              
1202             Provided with a string or a scalar reference, and this returns an hash reference containing details of the request line attributes if it is indeed a request, or an empty string if it is not a request.
1203              
1204             It sets an L<error|Module::Generic/error> and returns C<undef> upon error.
1205              
1206             The following attributes are available:
1207              
1208             =over 4
1209              
1210             =item C<http_version>
1211              
1212             The HTTP protocol version used. For example, in C<HTTP/1.1>, this would be C<1.1>, and in C<HTTP/2>, this would be C<2>.
1213              
1214             =item C<http_vers_minor>
1215              
1216             The HTTP protocol major version used. For example, in C<HTTP/1.0>, this would be C<1>, and in C<HTTP/2>, this would be C<2>.
1217              
1218             =item C<http_vers_minor>
1219              
1220             The HTTP protocol minor version used. For example, in C<HTTP/1.0>, this would be C<0>, and in C<HTTP/2>, this would be C<undef>.
1221              
1222             =item C<method>
1223              
1224             The HTTP request method used. For example in C<GET / HTTP/1.1>, this would be C<GET>. This uses the L<rfc7231 semantics|https://tools.ietf.org/html/rfc7231#section-4>, which means any token even non-standard ones would match.
1225              
1226             =item C<protocol>
1227              
1228             The HTTP protocol used, e.g. C<HTTP/1.0>, C<HTTP/1.1>, C<HTTP/2>, etc...
1229              
1230             =item C<uri>
1231              
1232             The request URI. For example in C<GET / HTTP/1.1>, this would be C</>
1233              
1234             =back
1235              
1236             my $ref = $p->looks_like_request( \$str );
1237             # or
1238             # my $ref = $p->looks_like_request( $str );
1239             die( $p->error ) if( !defined( $ref ) );
1240             if( $ref )
1241             {
1242             say "Request method $ref->{method}, uri $ref->{uri}, protocol $ref->{protocol}, version major $ref->{http_vers_major}, version minor $ref->{http_vers_minor}";
1243             }
1244             else
1245             {
1246             say "This is not an HTTP request.";
1247             }
1248              
1249             =head2 looks_like_response
1250              
1251             Provided with a string or a scalar reference, and this returns an hash reference containing details of the response line attributes if it is indeed a response, or an empty string if it is not a response.
1252              
1253             It sets an L<error|Module::Generic/error> and returns C<undef> upon error.
1254              
1255             The following attributes are available:
1256              
1257             =over 4
1258              
1259             =item C<code>
1260              
1261             The 3-digits HTTP response code. For example in C<HTTP/1.1 200 OK>, this would be C<200>.
1262              
1263             =item C<http_version>
1264              
1265             The HTTP protocol version used. For example, in C<HTTP/1.1>, this would be C<1.1>, and in C<HTTP/2>, this would be C<2>.
1266              
1267             =item C<http_vers_minor>
1268              
1269             The HTTP protocol major version used. For example, in C<HTTP/1.0>, this would be C<1>, and in C<HTTP/2>, this would be C<2>.
1270              
1271             =item C<http_vers_minor>
1272              
1273             The HTTP protocol minor version used. For example, in C<HTTP/1.0>, this would be C<0>, and in C<HTTP/2>, this would be C<undef>.
1274              
1275             =item C<protocol>
1276              
1277             The HTTP protocol used, e.g. C<HTTP/1.0>, C<HTTP/1.1>, C<HTTP/2>, etc...
1278              
1279             =item C<status>
1280              
1281             The response status text. For example in C<HTTP/1.1 200 OK>, this would be C<OK>.
1282              
1283             =back
1284              
1285             my $ref = $p->looks_like_response( \$str );
1286             # or
1287             # my $ref = $p->looks_like_response( $str );
1288             die( $p->error ) if( !defined( $ref ) );
1289             if( $ref )
1290             {
1291             say "Response code $ref->{code}, status $ref->{status}, protocol $ref->{protocol}, version major $ref->{http_vers_major}, version minor $ref->{http_vers_minor}";
1292             }
1293             else
1294             {
1295             say "This is not an HTTP response.";
1296             }
1297              
1298             =head2 looks_like_what
1299              
1300             Provided with a string or a scalar reference, and this returns an hash reference containing details of the HTTP message first line attributes if it is indeed an HTTP message.
1301              
1302             The attributes available depends on the type of HTTP message determined and are described in details in L</looks_like_request> and L</looks_like_response>. In addition to those, it also returns the attribute C<type>, which is a string representing the type of HTTP message this is, i.e. either C<request> or C<response>.
1303              
1304             If this does not match either an HTTP request or HTTP response, it returns an empty string.
1305              
1306             my $ref = $p->looks_like_what( \$str );
1307             die( $p->error ) if( !defined( $ref ) );
1308             say "This is a ", ( $ref ? $ref->{type} : 'unknown' ), " HTTP message.";
1309              
1310             my $ref = $p->looks_like_what( \$str );
1311             die( $p->error ) if( !defined( $ref ) );
1312             if( !$ref )
1313             {
1314             say "This is unknown.";
1315             }
1316             else
1317             {
1318             say "This is a HTTP $ref->{type} with protocol version $ref->{http_version}";
1319             }
1320              
1321             =head2 max_body_in_memory_size
1322              
1323             Integer. This is the threshold beyond which an entity body that is initially loaded into memory will switched to be loaded into a file on the local filesystem when it is a true value and exceeds the amount specified.
1324              
1325             By defaults, this has the value set by the class variable C<$MAX_BODY_IN_MEMORY_SIZE>, which is 102400 bytes or 100K
1326              
1327             =head2 max_headers_size
1328              
1329             Integer. This is the threshold size in bytes beyond which HTTP headers will trigger an error. This defaults to the class variable C<$MAX_HEADERS_SIZE>, which itself is set by default to 8192 bytes or 8K
1330              
1331             =head2 max_read_buffer
1332              
1333             Integer. This is the read buffer size. This is used for L<HTTP::Promise::IO> and this defaults to 2048 bytes (2Kb).
1334              
1335             =head2 new_tmpfile
1336              
1337             Creates a new temporary file. If C<tmp_to_core> is set to true, this will create a new file using a L<scalar object|Module::Generic::Scalar>, or it will create a new temporary file under the directory set with the object parameter C<tmp_dir>. The filehandle binmode is set to C<raw>.
1338              
1339             It returns a filehandle upon success, or upon error, it sets an L<error|Module::Generic/error> and return C<undef>.
1340              
1341             =head2 output_dir
1342              
1343             The filepath to the output directory. This is used when saving entity bodies on the filesystem.
1344              
1345             =head2 parse
1346              
1347             This takes a scalar reference of data, a glob or a file path, and will parse the HTTP request or response by calling L</parse_fh> and pass it whatever options it received.
1348              
1349             It returns an L<entity object|HTTP::Promise::Entity> upon success and upon error, it sets an L<error|Module::Generic/error> and return C<undef>.
1350              
1351             =head2 parse_data
1352              
1353             This takes a string or a scalar reference and returns an L<entity object|HTTP::Promise::Entity> upon success and upon error, it sets an L<error|Module::Generic/error> and return C<undef>
1354              
1355             =head2 parse_fh
1356              
1357             This takes a filehandle and parse the HTTP request or response, and returns an L<entity object|HTTP::Promise::Entity> upon success and upon error, it sets an L<error|Module::Generic/error> and return C<undef>.
1358              
1359             It takes also an hash or hash reference of the following options:
1360              
1361             =over 4
1362              
1363             =item * C<reader>
1364              
1365             An L<HTTP::Promise::IO>. If this is not provided, a new one will be created. Note that data will be read using this reader.
1366              
1367             =item * C<request>
1368              
1369             Boolean. Set this to true to indicate the data is an HTTP request. If neither C<request> nor C<response> is provided, the parser will attempt guessing it.
1370              
1371             =item * C<response>
1372              
1373             Boolean. Set this to true to indicate the data is an HTTP response. If neither C<request> nor C<response> is provided, the parser will attempt guessing it.
1374              
1375             =back
1376              
1377             =head2 parse_headers
1378              
1379             This takes a string or a scalar reference including a scalar object, such as L<Module::Generic::Scalar>, and an optional hash or hash reference of parameters and parse the headers found in the given string, if any at all.
1380              
1381             It returns an hash reference with the same property names and values returned by L</parse_headers_xs>.
1382              
1383             This method uses pure perl.
1384              
1385             Supported options are:
1386              
1387             =over 4
1388              
1389             =item * C<convert_dash>
1390              
1391             Boolean. If true, this will convert C<-> in header fields to C<_>. Default is false.
1392              
1393             =item * C<no_headers_ok>
1394              
1395             Boolean. If set to true, this won't trigger if there is no headers
1396              
1397             =back
1398              
1399             =head2 parse_headers_xs
1400              
1401             my $def = $p->parse_headers_xs( $http_request_or_response );
1402             my $def = $p->parse_headers_xs( $http_request_or_response, $options_hash_ref );
1403              
1404             This takes a string or a scalar reference including a scalar object, such as L<Module::Generic::Scalar>, and an optional hash or hash reference of parameters and parse the headers found in the given string, if any at all.
1405              
1406             It returns a dictionary as an hash reference upon success, and it sets an L<error|Module::Generic/error> with an http error code set and returns C<undef> upon error.
1407              
1408             Supported options are:
1409              
1410             =over 4
1411              
1412             =item * C<convert_dash>
1413              
1414             Boolean. If true, this will convert C<-> in header fields to C<_>. Default is false.
1415              
1416             =item * C<request>
1417              
1418             Boolean. If true, this will parse the string assuming it is a request header.
1419              
1420             =item * C<response>
1421              
1422             Boolean. If true, this will parse the string assuming it is a response header.
1423              
1424             =back
1425              
1426             The properties returned in the dictionary depend on whether C<request> or C<response> were enabled.
1427              
1428             For C<request>:
1429              
1430             =over 4
1431              
1432             =item * C<headers>
1433              
1434             An L<HTTP::Promise::Headers> object.
1435              
1436             =item * C<length>
1437              
1438             The length in bytes of the headers parsed.
1439              
1440             =item * C<method>
1441              
1442             The HTTP method such as C<GET>, or C<HEAD>, C<POST>, etc.
1443              
1444             =item * C<protocol>
1445              
1446             String, such as C<HTTP/1.1> or C<HTTP/2>
1447              
1448             =item * C<uri>
1449              
1450             String, the request URI, such as C</>
1451              
1452             =item * C<version>
1453              
1454             This is a L<version> object and contains a value such as C<1.1>, so you can do something like:
1455              
1456             if( $def->{version} >= version->parse( '1.1' ) )
1457             {
1458             # Do something
1459             }
1460              
1461             =back
1462              
1463             For C<response>:
1464              
1465             =over 4
1466              
1467             =item * C<code>
1468              
1469             The HTTP status code, such as C<200>
1470              
1471             =item * C<headers>
1472              
1473             An L<HTTP::Promise::Headers> object.
1474              
1475             =item * C<length>
1476              
1477             The length in bytes of the headers parsed. This is useful so you can then remove it from the string you provided:
1478              
1479             my $resp = <<EOT;
1480             HTTP/1.1 200 OK
1481             Content-Type: text/plain
1482              
1483             Hello world!
1484             EOT
1485             my $def = $p->parse_headers_xs( \$resp, response => 1 ) || die( $p->error );
1486             $str =~ /^\r?\n//;
1487             substr( $str, 0, $def->{length} ) = '';
1488             # $str now contains the body, i.e.: "Hello world!\n"
1489              
1490             =item * C<status>
1491              
1492             String, the HTTP status, i.e. something like C<OK>
1493              
1494             =item * C<protocol>
1495              
1496             String, such as C<HTTP/1.1>
1497              
1498             =item * C<version>
1499              
1500             This is a L<version> object and contains a value such as C<1.1>, so you can do something like:
1501              
1502             if( $def->{version} >= version->parse( '1.1' ) )
1503             {
1504             # Do something
1505             }
1506              
1507             =back
1508              
1509             If not enough data was provided to parse the headers, this will return an L<error object|Module::Generic/error> with code set to C<425> (Too early).
1510              
1511             If the headers is incomplete and the cumulated size exceeds the value set with L</max_headers_size>, this returns an L<error object|Module::Generic/error> with code set to C<413> (Request entity too large).
1512              
1513             If there are other issues with the headers, this sets the error code to C<400> (Bad request), and for any other error, this returns an error object without code.
1514              
1515             =head2 parse_multi_part
1516              
1517             This takes an hash or hash reference of options and parse an HTTP multipart portion of the HTTP request or response.
1518              
1519             It returns an L<entity object|HTTP::Promise::Entity> upon success and upon error it sets an L<error object|Module::Generic/error> and returns C<undef>.
1520              
1521             Supported options are:
1522              
1523             =over 4
1524              
1525             =item * C<entity>
1526              
1527             The L<HTTP::Property::Entity> object to which this multipart belongs.
1528              
1529             =item * C<reader>
1530              
1531             The L<HTTP::Property::Reader> used for reading the data chunks from the filehandle.
1532              
1533             =back
1534              
1535             =head2 parse_open
1536              
1537             Provided with a filepath, and this will open it in read mode, parse it and return an L<entity object|HTTP::Promise::Entity>.
1538              
1539             If there is an error, this returns C<undef> and you can retrieve the error by calling L<Module::Generic/error> which is inherited by this module.
1540              
1541             =head2 parse_request
1542              
1543             This takes a string or a scalar reference including a scalar object, such as L<Module::Generic::Scalar>, and an optional hash or hash reference of parameters and parse the request found in the given string, including the header and the body.
1544              
1545             It returns a dictionary as an hash reference upon success, and it sets an L<error|Module::Generic/error> with an http error code set and returns C<undef> upon error.
1546              
1547             The properties returned are the same as the ones returned for a C<request> by L</parse_headers_xs>, and also sets the C<content> property containing the body data of the request.
1548              
1549             Obviously this works well for simple request, i.e. not multipart ones, otherwise the entire body, whatever that is, will be stored in C<content>
1550              
1551             =head2 parse_request_headers
1552              
1553             This is an alias and is equivalent to calling L</parse_headers_xs> and setting the C<request> option.
1554              
1555             =head2 parse_request_line
1556              
1557             This takes a string or a scalar reference including a scalar object, such as L<Module::Generic::Scalar>, and parse the reuqest line returning an hash reference containing 4 properties: C<method>, C<path>, C<protocol>, C<version>
1558              
1559             =head2 parse_request_pp
1560              
1561             This is the same as L</parse_request>, except it uses the pure perl method L</parse_headers> to parse the headers instead of the XS one.
1562              
1563             =head2 parse_response
1564              
1565             This takes a string or a scalar reference including a scalar object, such as L<Module::Generic::Scalar>, and an optional hash or hash reference of parameters and parse the response found in the given string, including the header and the body.
1566              
1567             It returns a dictionary as an hash reference upon success, and it sets an L<error|Module::Generic/error> with an http error code set and returns C<undef> upon error.
1568              
1569             The properties returned are the same as the ones returned for a C<response> by L</parse_headers_xs>, and also sets the C<content> property containing the body data of the response.
1570              
1571             =head2 parse_response_headers
1572              
1573             This is an alias and is equivalent to calling L</parse_headers_xs> and setting the C<response> option.
1574              
1575             =head2 parse_response_line
1576              
1577             This takes a string or a scalar reference including a scalar object, such as L<Module::Generic::Scalar>, and parse the reuqest line returning an hash reference containing 4 properties: C<method>, C<path>, C<protocol>, C<version>
1578              
1579             =head2 parse_response_pp
1580              
1581             This is the same as L</parse_response>, except it uses the pure perl method L</parse_headers> to parse the headers instead of the XS one.
1582              
1583             =head2 parse_singleton
1584              
1585             Provided with an hash or hash reference of options and this parse a simple entity body.
1586              
1587             It returns an L<entity object|HTTP::Promise::Entity> upon success and upon error it sets an L<error object|Module::Generic/error> and returns C<undef>.
1588              
1589             Supported options are:
1590              
1591             =over 4
1592              
1593             =item * C<entity>
1594              
1595             The L<HTTP::Property::Entity> object to which this multipart belongs.
1596              
1597             =item * C<read_until>
1598              
1599             A string or a regular expression that indicates the string up to which to read data from the filehandle.
1600              
1601             =item * C<reader>
1602              
1603             The L<HTTP::Property::Reader> used for reading the data chunks from the filehandle.
1604              
1605             =back
1606              
1607             =head2 parse_version
1608              
1609             This takes an HTTP version string, such as C<HTTP/1.1> or C<HTTP/2> and returns its major and minor as a 2-elements array in list context, or just the L<version> object in scalar context.
1610              
1611             =head2 tmp_dir
1612              
1613             Sets or gets the temporary directory to use when creating temporary files.
1614              
1615             When set, this returns a L<file object|Module::Generic::File>
1616              
1617             =head2 tmp_to_core
1618              
1619             Boolean. When set to true, this will store data in memory rather than in a file on the filesystem.
1620              
1621             =head1 AUTHOR
1622              
1623             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
1624              
1625             =head1 SEE ALSO
1626              
1627             L<rfc6266 on Content-Disposition|https://datatracker.ietf.org/doc/html/rfc6266>,
1628             L<rfc7230 on Message Syntax and Routing|https://tools.ietf.org/html/rfc7230>,
1629             L<rfc7231 on Semantics and Content|https://tools.ietf.org/html/rfc7231>,
1630             L<rfc7232 on Conditional Requests|https://tools.ietf.org/html/rfc7232>,
1631             L<rfc7233 on Range Requests|https://tools.ietf.org/html/rfc7233>,
1632             L<rfc7234 on Caching|https://tools.ietf.org/html/rfc7234>,
1633             L<rfc7235 on Authentication|https://tools.ietf.org/html/rfc7235>,
1634             L<rfc7578 on multipart/form-data|https://tools.ietf.org/html/rfc7578>,
1635             L<rfc7540 on HTTP/2.0|https://tools.ietf.org/html/rfc7540>
1636              
1637             L<Mozilla documentation on HTTP protocol|https://developer.mozilla.org/en-US/docs/Web/HTTP/Resources_and_specifications>
1638              
1639             L<Mozilla documentation on HTTP messages|https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages>
1640              
1641             L<Mozilla documentation|https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST>
1642              
1643             L<HTTP::Promise>, L<HTTP::Promise::Request>, L<HTTP::Promise::Response>, L<HTTP::Promise::Message>, L<HTTP::Promise::Entity>, L<HTTP::Promise::Headers>, L<HTTP::Promise::Body>, L<HTTP::Promise::Body::Form>, L<HTTP::Promise::Body::Form::Data>, L<HTTP::Promise::Body::Form::Field>, L<HTTP::Promise::Status>, L<HTTP::Promise::MIME>, L<HTTP::Promise::Parser>, L<HTTP::Promise::IO>, L<HTTP::Promise::Stream>, L<HTTP::Promise::Exception>
1644              
1645             =head1 COPYRIGHT & LICENSE
1646              
1647             Copyright(c) 2022 DEGUEST Pte. Ltd.
1648              
1649             All rights reserved.
1650              
1651             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
1652              
1653             =cut