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   1579135 use strict;
  11         61  
  11         410  
18 11     11   74 use warnings;
  11         39  
  11         348  
19 11     11   82 use warnings::register;
  11         32  
  11         1620  
20 11     11   120 use parent qw( Module::Generic );
  11         23  
  11         142  
21 11         2026 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   100666 $DEFAULT_MIME_TYPE );
  11         29  
25 11     11   93 use version;
  11         33  
  11         129  
26             # use HTTP::Parser::XS 0.17 ();
27 11     11   6281 use HTTP::Parser2::XS 0.01 ();
  11         5733  
  11         354  
28 11     11   7541 use HTTP::Promise::Entity;
  11         47  
  11         113  
29 11     11   3719 use HTTP::Promise::Headers;
  11         25  
  11         332  
30 11     11   4448 use HTTP::Promise::IO;
  11         40  
  11         122  
31 11     11   3065 use Module::Generic::File qw( sys_tmpdir );
  11         35  
  11         102  
32             # use Nice::Try;
33 11     11   3083 use URI;
  11         27  
  11         356  
34 11     11   4813 use URI::Encode::XS;
  11         5726  
  11         515  
35 11     11   75 use Want;
  11         35  
  11         638  
36             use constant (
37 11         4982 TYPE_URL_ENCODED => 'application/x-www-form-urlencoded',
38 11     11   64 );
  11         32  
39 11     11   54 our @EXPORT = ();
40 11         52 our @EXPORT_OK = qw( parse_headers parse_request parse_request_line parse_response
41             parse_response_line parse_version );
42 11         121 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         76 our $CRLF = qr/\x0D?\x0A/;
50 11         410 our $LWS = qr/$CRLF[\x09\x20]|[\x09\x20]/;
51 11         63 our $TEXT = qr/[\x20-\xFF]/;
52             # !, #, $, %, &, ', *, +, -, ., 0..9, A..Z, ^, _, `, a..z, |, ~
53 11         58 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         652 our $HEADER = qr/($TOKEN+)$LWS*:$LWS*((?:$TEXT|$LWS)*)$CRLF/;
59             # HTTP/1.0, HTTP/1.1, HTTP/2
60 11         105 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         491 our $REQUEST = qr/(?<method>$TOKEN+)[\x09\x20]+(?<uri>[\x21-\xFF]+)[\x09\x20]+(?<protocol>$HTTP_VERSION)$CRLF/;
64 11         537 our $REQUEST_RFC2616 = qr/(?:$CRLF)*($TOKEN+)[\x09\x20]+([\x21-\xFF]+)(?:[\x09\x20]+($HTTP_VERSION))?$CRLF/;
65 11         436 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         50 our $MAX_HEADERS_SIZE = 8192;
70 11         19 our $MAX_READ_BUFFER = 2048;
71             # 100Kb
72 11         21 our $MAX_BODY_IN_MEMORY_SIZE = 102400;
73 11         31 our $DEFAULT_MIME_TYPE = 'application/octet-stream';
74 11         16 our $ERROR = '';
75 11         33 our $DEBUG = 0;
76 11         19 our $EXCEPTION_CLASS = 'HTTP::Promise::Exception';
77 11         396 our $VERSION = 'v0.2.0';
78             };
79              
80 11     11   99 use strict;
  11         32  
  11         400  
81 11     11   61 use warnings;
  11         26  
  11         78163  
82              
83             sub init
84             {
85 35     35 1 1174704 my $self = shift( @_ );
86 35         805 $self->{decode_body} = 1;
87 35         169 $self->{decode_headers} = 0;
88 35         113 $self->{ignore_filename}= 0;
89 35         165 $self->{max_body_in_memory_size} = $MAX_BODY_IN_MEMORY_SIZE;
90 35         109 $self->{max_headers_size} = $MAX_HEADERS_SIZE;
91 35         118 $self->{max_read_buffer} = $MAX_READ_BUFFER;
92 35         268 $self->{output_dir} = sys_tmpdir();
93 35         5029506 $self->{tmp_dir} = undef;
94 35         264 $self->{tmp_to_core} = 0;
95 35         164 $self->{_init_strict_use_sub} = 1;
96 35         247 $self->{_exception_class} = $EXCEPTION_CLASS;
97 35 50       736 $self->SUPER::init( @_ ) || return( $self->pass_error );
98 35         6158 my $dir = $self->output_dir;
99 35 50 33     31279 return( $self->error( "No output directory set." ) ) if( !defined( $dir ) || !length( $dir ) );
100 35 50       1141 return( $self->error( "Output directory set \"$dir\" does not exist." ) ) if( !$dir->exists );
101 35 50       3430 return( $self->error( "Output directory set \"$dir\" is not actually a directory." ) ) if( !$dir->is_dir );
102 35         2338 return( $self );
103             }
104              
105 4     4 1 142877 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 21 my $self = shift( @_ );
150 2         16 my $this = shift( @_ );
151             # Shortcut
152 2 50       31 return( '' ) if( !defined( $this ) );
153 2 50 33     23 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       19 my $ref = $self->_is_scalar( $this ) ? $this : \$this;
155             # No need to go further
156 2 50 33     63 return( '' ) if( !defined( $$ref ) || !length( $$ref ) );
157 2         7 my( $type, $def );
158 2 100       291 if( $$ref =~ /^$REQUEST/ )
    50          
159             {
160 1         47 $def = {%+};
161 1         11 $type = 'request';
162             }
163             elsif( $$ref =~ /^$RESPONSE/ )
164             {
165 1         79 $def = {%+};
166 1         15 $type = 'response';
167             }
168             # undef is for errors
169 2 50       22 return( '' ) if( !defined( $def ) );
170 2         14 $def->{type} = $type;
171 2         15 return( $def );
172             }
173              
174 27     27 1 146 sub max_body_in_memory_size { return( shift->_set_get_number( 'max_body_in_memory_size', @_ ) ); }
175              
176 32     32 1 257 sub max_headers_size { return( shift->_set_get_number( 'max_headers_size', @_ ) ); }
177              
178 20     20 1 471 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 698 sub output_dir { return( shift->_set_get_file( 'output_dir', @_ ) ); }
200              
201             sub parse
202             {
203 23     23 1 61262 my $self = shift( @_ );
204 23   50     170 my $this = shift( @_ ) || return( $self->error( "Nothing to parse was provided." ) );
205             # Can be glob, scalar reference, file path
206 23         138 my $io;
207 23 100       276 if( $self->_is_glob( $this ) )
    100          
208             {
209 4         104 $io = $this;
210             }
211             elsif( $self->_is_scalar( $this ) )
212             {
213 17 50       675 $self->_load_class( 'Module::Generic::Scalar::IO' ) ||
214             return( $self->pass_error );
215 17   50     7545 $io = Module::Generic::Scalar::IO->new( $this, '<' ) ||
216             return( $self->pass_error( Module::Generic::Scalar::IO->error ) );
217             }
218             else
219             {
220 2   50     115 my $f = $self->new_file( $this ) || return( $self->pass_error );
221 2   100     258607 $io = $f->open( '<', { binmode => 'raw' } ) || return( $self->pass_error( $f->error ) );
222             }
223 22         23957 return( $self->parse_fh( $io, @_ ) );
224             }
225              
226             sub parse_data
227             {
228 1     1 1 4122 my $self = shift( @_ );
229 1 50 33     16 return( $self->error( "Invalid argument. parse_data() only accepts either a string or something that stringifies." ) ) if( ref( $_[0] ) && !overload::Method( $_[0] => '""' ) );
230 1         12 return( $self->parse( \"$_[0]" ) );
231             }
232              
233             sub parse_fh
234             {
235 22     22 1 134 my $self = shift( @_ );
236 22         88 my $fh = shift( @_ );
237 22 50       124 return( $self->error( "No filehandle was provided to read from." ) ) if( !defined( $fh ) );
238 22 50       177 return( $self->error( "Filehandle provided (", overload::StrVal( $fh ), ") is not a valid filehandle." ) ) if( !$self->_is_glob( $fh ) );
239 22         489 my $opts = $self->_get_args_as_hash( @_ );
240 22         1152 my $reader;
241 22 100       299 if( $reader = $opts->{reader} )
242             {
243 2 50       48 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     157 $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         557 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       77048 return( $self->pass_error( $reader->error ) ) if( !defined( $buff ) );
256 22 50 66     325 unless( $opts->{request} || $opts->{response} )
257             {
258             # Ref: <https://tools.ietf.org/html/rfc7230#section-3.1.2>
259 18 100       1096 if( $buff =~ m,^(${HTTP_VERSION})[[:blank:]]+, )
    100          
260             {
261 2         18 $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         37 $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         218 my $max = $self->max_headers_size;
280 22         815302 my( $n, $def, $headers );
281 22         74 $n = -1;
282 22         127 while( $n != 0 )
283             {
284 25         3397 $n = $reader->read( $buff, 2048, length( $buff ) );
285 25 50       2787 return( $self->pass_error( $reader->error ) ) if( !defined( $n ) );
286 25 100       169 if( $n == 0 )
287             {
288 7 50       50 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         104 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     2681 if( $opts->{request} || $opts->{response} )
300             {
301 9         144 $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         455 $def = $self->parse_headers( \$buff, $opts );
308             }
309            
310 18 100       27401 if( !defined( $def ) )
311             {
312             # 400 Bad request
313 4 50 66     25 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       3838 next if( $self->error->code == 425 );
316             # For other errors, we stop and pass the error received
317 1         896 return( $self->pass_error );
318             }
319             else
320             {
321             $headers = $def->{headers} ||
322 14   50     104 return( $self->error( "No headers object set by parse_headers_xs() !" ) );
323 14 50       149 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       381 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         72 substr( $buff, 0, $def->{length}, '' );
326 14 50       164 $reader->unread( $buff ) if( length( $buff ) );
327 14         46 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         507 my $trash = $reader->read_until_in_memory( qr/${CRLF}/, include => 1 );
333            
334 14         2255 my $ent = HTTP::Promise::Entity->new( headers => $headers, debug => $DEBUG );
335 14 50 100     354 if( ( $opts->{request} || $opts->{response} ) && $def->{protocol} )
      66        
336             {
337 9         35 my $message;
338 9 100       43 if( $opts->{request} )
339             {
340 7 50       58 $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     1492 debug => $DEBUG
345             } ) ||
346             return( $self->pass_error( HTTP::Promise::Request->error ) );
347             }
348             else
349             {
350 2 50       29 $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     599 debug => $DEBUG
355             } ) ||
356             return( $self->pass_error( HTTP::Promise::Response->error ) );
357             }
358             # Mutual assignment for convenience
359 8         124 $message->entity( $ent );
360 8         327 $ent->http_message( $message );
361             }
362 13         431 my $type = $ent->mime_type;
363 13         38 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       79 if( $type =~ m,^multipart/,i )
370             {
371 3   50     37 $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         301 for( $ent->parts->list )
375             {
376 12 100       4386 if( my $dispo = $_->headers->content_disposition )
377             {
378 4         137 my $cd = $_->headers->new_field( 'Content-Disposition' => $dispo );
379 4 50       25 return( $self->pass_error( $_->headers->error ) ) if( !defined( $cd ) );
380 4 50       31 if( my $name = $cd->name )
381             {
382 4         2183 $_->name( $name );
383             }
384             }
385             }
386             }
387             else
388             {
389 10   50     170 $part_ent = $self->parse_singleton( entity => $ent, reader => $reader ) ||
390             return( $self->pass_error );
391             }
392 13         1404 return( $ent );
393             }
394              
395             sub parse_headers($$)
396             {
397 57     57 1 858 my $self = shift( @_ );
398 57         274 my $str = $self->_get_args( shift( @_ ) );
399 57 50       220 return( $self->pass_error ) if( !defined( $str ) );
400 57         384 my $opts = $self->_get_args_as_hash( @_ );
401 57   50     4031 $opts->{convert_dash} //= 0;
402 57   100     371 $opts->{no_headers_ok} //= 0;
403 57 50       207 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       873 if( $$str !~ /${CRLF}${CRLF}/ )
413             {
414 7         108 return( $self->error({ code => 425, message => 'Incomplete request, call again when there is more data.', class => $EXCEPTION_CLASS }) );
415             }
416            
417 50         157 my $def = {};
418 50         187 pos( $$str ) = 0;
419 50 100       1897 if( $$str =~ m,^(${HTTP_VERSION})[[:blank:]]+(?<code>\d{3})[[:blank:]]+(?<status>.*?)$CRLF,gc )
    100          
    100          
    100          
420             {
421 9         118 @$def{qw( protocol code status )} = @+{qw( http_protocol code status )};
422 9         101 $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         305 @$def{qw( method uri protocol )} = @+{qw( method uri http_protocol )};
431 9         219 $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         41 @$def{qw( method uri )} = ( $1, $2 );
439 2         20 $def->{protocol} = 'HTTP/0.9';
440 2         35 $def->{version} = version->parse( '0.9' );
441             # There should not be any header in a simple request
442 2 50       133 return( $self->error({ code => 400, message => 'Bad request', class => $EXCEPTION_CLASS }) ) if( $$str =~ /^$HEADER/ );
443 2         23 $def->{length} = pos( $$str );
444 2         37 $def->{headers} = HTTP::Promise::Headers->new;
445 2         16 return( $def );
446             }
447             elsif( $$str =~ /^(?:[A-Z]+\/\d+\.\d+|[A-Z]+[[:blank:]\h]+(?!\:))/ )
448             {
449 5 100       27 my $type = $$str =~ m,^[A-Z]+\/\d+\.\d+, ? 'Response' : 'Request';
450 5         42 return( $self->error({ code => 400, message => "Bad ${type}-Line", class => $EXCEPTION_CLASS }) );
451             }
452              
453 43 100 100     1377 if( pos( $$str ) == 0 && $$str !~ /^$HEADER/ )
454             {
455 4         87 return( $self->error({ code => 400, message => 'Bad request', class => $EXCEPTION_CLASS }) );
456             }
457              
458 39         269 my $headers = $self->new_array;
459            
460 39         951 my $len = 0;
461             # my $remain = CORE::length( $$str );
462             # while( $$str =~ s/^$HEADER// )
463 39         845 while( $$str =~ /\G$HEADER/gc )
464             {
465             # $len += ( $remain - CORE::length( $$str ) );
466             # $remain = CORE::length( $$str );
467 59         871 my( $n, $v ) = ( lc( $1 ), $2 );
468 59 50       183 $n =~ tr/-/_/ if( $opts->{convert_dash} );
469 59         248 $headers->push( $n => $v );
470             }
471 39         430 $len = pos( $$str );
472            
473 39 100       398 unless( $$str =~ /\G${CRLF}/gc )
474             {
475 2 100       13 my $type = $def->{code} ? 'response' : 'request';
476 2         39 return( $self->error({ code => 400, message => "Bad ${type}", class => $EXCEPTION_CLASS }) );
477             }
478              
479 37         173 foreach( @$headers )
480             {
481 118         1195 s/$LWS+/\x20/g;
482 118         455 s/^$LWS//;
483 118         558 s/$LWS$//;
484             }
485             # return( want( 'LIST' ) ? $headers->list : $headers );
486 37         257 $def->{length} = $len;
487 37         585 $def->{headers} = HTTP::Promise::Headers->new( @$headers );
488 37         221 return( $def );
489             }
490              
491             sub parse_headers_xs($$)
492             {
493 10     10 1 42 my $self = shift( @_ );
494 10   50     113 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
495 10         60 my $opts = $self->_get_args_as_hash( @_ );
496 10 50 66     2058 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     75 my $max_headers_size = $self->max_headers_size // 0;
502            
503 10         45820 my $r = {};
504 10         49 my $len;
505             my $bkp_version;
506             # try-catch
507 10         25 local $@;
508             eval
509 10         34 {
510 10 100       66 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       50 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         374 $len = HTTP::Parser2::XS::parse_http_request( $$str, $r );
524             }
525             elsif( $opts->{response} )
526             {
527 2 50       38 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         102 $len = HTTP::Parser2::XS::parse_http_response( $$str, $r );
535             }
536             };
537 10 50       64 if( $@ )
538             {
539 0         0 return( $self->error({ code => 400, message => $@, class => $EXCEPTION_CLASS }) );
540             }
541            
542 10 50 33     140 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       48 $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         60 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         54 my $headers = $self->new_array;
595             # Skip keys that start with _. They are private properties
596 10         464 for( sort( grep( !/^_/, keys( %$r ) ) ) )
597             {
598 39         236 my $k = $_;
599 39 50       94 $k =~ tr/-/_/ if( $opts->{convert_dash} );
600 39         148 $headers->push( $k => $r->{ $_ } );
601             }
602 10         451 $def->{headers} = HTTP::Promise::Headers->new( @$headers );
603 10 100       103 if( $opts->{request} )
    50          
604             {
605 8         84 @$def{qw( method protocol )} = @$r{qw( _method _protocol )};
606 8 50 33     171 $def->{uri} = URI->new( $r->{_request_uri} ) if( exists( $r->{_request_uri} ) && length( $r->{_request_uri} ) );
607             }
608             elsif( $opts->{response} )
609             {
610 2         36 @$def{qw( code status protocol )} = @$r{qw( _status _message _protocol )};
611             }
612 10   50     1123 $def->{version} = $self->parse_version( $r->{_protocol} ) || return( $self->pass_error );
613             # It seems
614 10         1274 while( substr( $$str, 0, $len ) =~ /$CRLF($CRLF)$/ )
615             {
616 10         114 $len -= length( $1 );
617             }
618 10         42 $def->{length} = $len;
619 10         52 return( $def );
620             }
621              
622             sub parse_multi_part
623             {
624 4     4 1 25 my $self = shift( @_ );
625 4         26 my $opts = $self->_get_args_as_hash( @_ );
626             my $ent = $opts->{entity} ||
627 4   50     663 return( $self->error({ code => 500, message => "No entity object was provided." }) );
628             my $reader = $opts->{reader} ||
629 4   50     20 return( $self->error({ code => 500, message => "No reader object was provided." }) );
630 4   50     16 my $headers = $ent->headers ||
631             return( $self->error({ code => 500, message => "No headers object found in entity object." }) );
632 4         123 my $ct = $headers->content_type;
633 4   50     73 my $h = $headers->new_field( 'Content-Type' => $ct ) || return( $self->pass_error( $headers->error ) );
634 4   50     22 my $boundary = $h->boundary ||
635             return( $self->error( "No boundary could be found in the Content-Type header '$ct'" ) );
636 4         2106 my $max_in_memory = $self->max_body_in_memory_size;
637 4   50     108958 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         164 my $trash = $reader->read_until_in_memory( qr/--${boundary}${CRLF}/, include => 1, capture => 1 );
641 4 50       543 return( $self->pass_error( $reader->error ) ) if( !defined( $trash ) );
642 4 50       38 return( $self->error( "Unable to find the initial boundary '${boundary}'" ) ) if( !length( $trash ) );
643 4         19 my $delim = $reader->last_delimiter;
644 4         3156 my $preamble;
645 4 50       17 if( length( $delim ) )
646             {
647 4         55 $preamble = substr( $trash, 0, index( $trash, $delim ) );
648 4         69 $self->_trim_crlf( \$preamble );
649 4 100       56 $ent->preamble( [split( /$CRLF/, $preamble )] ) if( length( $preamble ) );
650             }
651            
652 4         1469 my( $buff, $mime, $def );
653 4         8 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         511 my $hdr = $reader->read_until_in_memory( qr/(?:^${CRLF}|(?:(?:$TOKEN+)[\x09\x20]*\:(?:.+?)${CRLF}${CRLF}))/, include => 1 );
658 14 50       1933 return( $self->pass_error( $reader->error ) ) if( !defined( $hdr ) );
659 14 50       59 last if( !length( $hdr ) );
660 14         37 my( $ph, $file, $mime_type, $ext, $io );
661 14 100 66     300 if( length( $hdr ) && $hdr !~ /^$CRLF$/ )
662             {
663 10   50     91 $def = $self->parse_headers( $hdr ) || return( $self->pass_error );
664 10         283 $ph = $def->{headers};
665 10         78 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         67 $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       84 $reader->unread( $hdr ) if( $hdr =~ /^$CRLF$/ );
675 4         96 $ph = HTTP::Promise::Headers->new;
676             }
677 14   50     93 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     195 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     12 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         192 my $trash = $reader->read_until_in_memory( qr/${CRLF}--${boundary}(?:\-{2})?${CRLF}/, include => 1, capture => 1 );
688 1         184 my $delim = $reader->last_delimiter;
689 1         843 my $epilogue;
690 1 50       4 if( length( $delim ) )
691             {
692 1         10 $epilogue = substr( $trash, 0, index( $trash, $delim ) );
693 1         29 $self->_trim_crlf( \$epilogue );
694 1 50       45 $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         832 for( $part_ent->parts->list )
698             {
699 2 50       1493 if( my $dispo = $_->headers->content_disposition )
700             {
701 2         66 my $cd = $_->headers->new_field( 'Content-Disposition' => $dispo );
702 2 50       12 return( $self->pass_error( $_->headers->error ) ) if( !defined( $cd ) );
703 2 50       8 if( my $name = $cd->name )
704             {
705 2         1143 $_->name( $name );
706             }
707             }
708             }
709             }
710             # Otherwise, we are dealing with a simple part
711             else
712             {
713 13   50     438 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         2181 $ent->parts->push( $part_ent );
720             # Have we reached the last delimiter yet?
721 14         9182 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       13019 last if( $last =~ /\-\-${boundary}\-\-${CRLF}$/ );
725             }
726 4         142 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 29 my $self = shift( @_ );
759 1   50     31 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
760 1         40 my $opts = $self->_get_args_as_hash( @_ );
761 1         13 $opts->{request} = 1;
762 1         17 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 80633 my $self = shift( @_ );
785 19   50     184 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
786 19   100     157 my $req = $self->parse_headers( $str, @_ ) || return( $self->pass_error );
787 10         275 substr( $$str, 0, $req->{length}, '' );
788 10 100       183 $$str =~ s/^$CRLF// or return( $self->error({ code => 400, message => 'Bad request', class => $EXCEPTION_CLASS }) );
789 9 100       533 if( $req->{version} < version->parse( '1.0' ) )
790             {
791 1 50       16 $$str eq '' or return( $self->error({ code => 400, message => 'Bad request', class => $EXCEPTION_CLASS }) );
792             }
793 9         94 $req->{content} = $str;
794 9         73 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 56969 my $self = shift( @_ );
837 13   50     47 my $str = $self->_get_args( shift( @_ ) ) || return( $self->pass_error );
838 13         40 my $opts = $self->_get_args_as_hash( @_ );
839 13         75 $opts->{no_headers_ok} = 1;
840 13   100     35 my $resp = $self->parse_headers( $str, $opts ) || return( $self->pass_error );
841 8         155 substr( $$str, 0, $resp->{length}, '' );
842 8 50       85 $$str =~ s/^$CRLF// or return( $self->error({ code => 400, message => 'Bad response', class => $EXCEPTION_CLASS }) );
843 8         16 $resp->{content} = $str;
844 8         25 return( $resp );
845             }
846              
847             # Called when there is no multipart
848             sub parse_singleton
849             {
850 23     23 1 91 my $self = shift( @_ );
851 23         152 my $opts = $self->_get_args_as_hash( @_ );
852             my $ent = $opts->{entity} ||
853 23   50     4079 return( $self->error({ code => 500, message => "No entity object was provided." }) );
854             my $reader = $opts->{reader} ||
855 23   50     136 return( $self->error({ code => 500, message => "No reader object was provided." }) );
856 23   50     90 my $headers = $ent->headers ||
857             return( $self->error({ code => 500, message => "No headers object found in entity object." }) );
858 23         700 my $type = $headers->type;
859 23         91 my $read_until = $opts->{read_until};
860 23         333 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     381380 my $default_mime = $DEFAULT_MIME_TYPE || 'application/octet-stream';
865 23         165 my $len = $headers->content_length;
866 23         35089 my $chunk_size = 2048;
867 23         85 my( $body, $file, $mime_type, $mime, $ext );
868 23         102 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         309 };
884            
885 23 100 66     150 if( defined( $len ) && !defined( $read_until ) )
886             {
887             # Nothing to be done. The body is zero byte, like in HEAD request
888 1 50       6 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         217 my $bytes = $reader->read( $data, $len );
921 1 50       201 return( $self->error( "Error reading HTTP body from filehandle: ", $reader->error ) ) if( !defined( $bytes ) );
922             # Assignment used for the warning below
923 1         3 $total_bytes = $bytes;
924             }
925 1 50 33     7 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         125 my $buff = '';
931 22         63 my $bytes = -1;
932 22         46 my $io;
933 22         82 while( $bytes )
934             {
935 25 100       394 if( defined( $read_until ) )
936             {
937 13         129 $bytes = $reader->read_until( $buff, $chunk_size, { string => $read_until, ignore => 1, capture => 1 } );
938             }
939             else
940             {
941 12         91 $bytes = $reader->read( $buff, $chunk_size );
942             }
943 25 50       878 return( $self->pass_error( $reader->error ) ) if( !defined( $bytes ) );
944            
945 25 50       200 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         3516 $data .= $buff;
966             }
967             # reader returns negative bytes if those are the last bytes read until it reached the boundary
968 25 100       159 last if( $bytes < 0 );
969             }
970 22 50       108 $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       216 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     204 if( defined( $type ) && $type eq TYPE_URL_ENCODED )
1017             {
1018 1   50     29 $body = $ent->new_body( form => $data ) ||
1019             return( $self->pass_error( $ent->error ) );
1020             }
1021             else
1022             {
1023 22   50     353 $body = $ent->new_body( string => $data ) ||
1024             return( $self->pass_error( $ent->error ) );
1025             }
1026             }
1027 23         240 $ent->body( $body );
1028 23         1596 my $enc = $headers->content_encoding;
1029 23 50 66     187 if( $enc && $body->length && $self->decode_body( $enc ) )
      66        
1030             {
1031 4 50       3198 $ent->decode_body( $enc ) || return( $self->pass_error( $ent->error ) );
1032 4         50 $ent->is_encoded(0);
1033             }
1034 23         3681 return( $ent );
1035             }
1036              
1037             sub parse_version($$)
1038             {
1039 10     10 1 52 my $self = shift( @_ );
1040 10         50 my $str = shift( @_ );
1041 10 50 33     132 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       460 $str =~ m/^${HTTP_VERSION}$/ or
1043             return( $self->error({ code => 400, message => "Bad HTTP-Version '$str'", class => $EXCEPTION_CLASS }) );
1044 10         200 my $major = $+{http_vers_major};
1045             # May be undef if HTTP/2 for example
1046 10         75 my $minor = $+{http_vers_minor};
1047 10         260 my $v = version->parse( $+{http_version} );
1048 10 50       94 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   252 my $self = shift( @_ );
1058 100         193 my $str = shift( @_ );
1059 100 100       505 if( !ref( $str ) )
    50          
1060             {
1061 16         109 $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         1052 return( $str );
1068             }
1069              
1070             sub _trim_crlf
1071             {
1072 5     5   19 my $self = shift( @_ );
1073 5         11 my $ref = shift( @_ );
1074 5 50       20 return( $ref ) if( !defined( $ref ) );
1075 5 50       22 die( "Bad argument. This must be provided a scalar reference.\n" ) if( !$self->_is_scalar( $ref ) );
1076 5         60 my $n = 0;
1077 5   66     90 substr( $$ref, $n, 1, '' ), $n++ while( substr( $$ref, $n, 1 ) eq "\015" || substr( $$ref, $n, 1 ) eq "\012" );
1078 5         20 $n = length( $$ref );
1079 5   66     71 $n-- while( substr( $$ref, ($n - 1), 1 ) eq "\015" || substr( $$ref, ($n - 1), 1 ) eq "\012" );
1080 5         25 substr( $$ref, $n, length( $$ref ), '' );
1081 5         15 return( $ref );
1082             }
1083              
1084             # NOTE: sub FREEZE is inherited
1085              
1086 1     1 0 210 sub STORABLE_freeze { CORE::return( CORE::shift->FREEZE( @_ ) ); }
1087              
1088 1     1 0 7180 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