File Coverage

blib/lib/Plack/HTTPParser/PP.pm
Criterion Covered Total %
statement 53 55 96.3
branch 13 20 65.0
condition 6 10 60.0
subroutine 5 5 100.0
pod 0 1 0.0
total 77 91 84.6


line stmt bran cond sub pod time code
1             package Plack::HTTPParser::PP;
2 40     40   70936 use strict;
  40         87  
  40         1539  
3 40     40   285 use warnings;
  40         80  
  40         1787  
4 40     40   1735 use URI::Escape;
  40         6751  
  40         43299  
5              
6             sub parse_http_request {
7 710     710 0 5226 my($chunk, $env) = @_;
8 710   50     3032 $env ||= {};
9              
10             # pre-header blank lines are allowed (RFC 2616 4.1)
11 710         13733 $chunk =~ s/^(\x0d?\x0a)+//;
12 710 50       3285 return -2 unless length $chunk;
13              
14             # double line break indicates end of header; parse it
15 710 50       17531 if ($chunk =~ /^(.*?\x0d?\x0a\x0d?\x0a)/s) {
16 710         14906 return _parse_header($chunk, length $1, $env);
17             }
18 0         0 return -2; # still waiting for unknown amount of header lines
19             }
20              
21             sub _parse_header {
22 710     710   4421 my($chunk, $eoh, $env) = @_;
23              
24 710         4591 my $header = substr($chunk, 0, $eoh,'');
25 710         2107 $chunk =~ s/^\x0d?\x0a\x0d?\x0a//;
26              
27             # parse into lines
28 710         10004 my @header = split /\x0d?\x0a/,$header;
29 710         3931 my $request = shift @header;
30              
31             # join folded lines
32 710         1582 my @out;
33 710         2136 for(@header) {
34 2452 100       7432 if(/^[ \t]+/) {
35 2 50       6 return -1 unless @out;
36 2         6 $out[-1] .= $_;
37             } else {
38 2450         8669 push @out, $_;
39             }
40             }
41              
42             # parse request or response line
43 710         1879 my $obj;
44 710         2744 my ($major, $minor);
45              
46 710         3992 my ($method,$uri,$http) = split / /,$request;
47 710 50 33     12869 return -1 unless $http and $http =~ /^HTTP\/(\d+)\.(\d+)$/i;
48 710         11456 ($major, $minor) = ($1, $2);
49              
50 710         4699 $env->{REQUEST_METHOD} = $method;
51 710         3717 $env->{SERVER_PROTOCOL} = "HTTP/$major.$minor";
52 710         2200 $env->{REQUEST_URI} = $uri;
53              
54 710         6509 my($path, $query) = ( $uri =~ /^([^?]*)(?:\?(.*))?$/s );
55 710 100 66     2448 for ($path, $query) { s/\#.*$// if defined && length } # dumb clients sending URI fragments
  1420         11829  
56              
57 710         15810 $env->{PATH_INFO} = URI::Escape::uri_unescape($path);
58 710   100     22138 $env->{QUERY_STRING} = $query || '';
59 710         2698 $env->{SCRIPT_NAME} = '';
60              
61             # import headers
62 710         9704 my $token = qr/[^][\x00-\x1f\x7f()<>@,;:\\"\/?={} \t]+/;
63 710         2025 my $k;
64 710         6463 for my $header (@out) {
65 2450 50       21994 if ( $header =~ s/^($token): ?// ) {
    0          
66 2450         7927 $k = $1;
67 2450         8306 $k =~ s/-/_/g;
68 2450         6840 $k = uc $k;
69              
70 2450 100       6848 if ($k !~ /^(?:CONTENT_LENGTH|CONTENT_TYPE)$/) {
71 2234         6121 $k = "HTTP_$k";
72             }
73             } elsif ( $header =~ /^\s+/) {
74             # multiline header
75             } else {
76 0         0 return -1;
77             }
78              
79 2450 100       6622 if (exists $env->{$k}) {
80 19         346 $env->{$k} .= ", $header";
81             } else {
82 2431         11800 $env->{$k} = $header;
83             }
84             }
85              
86 710         5884 return $eoh;
87             }
88              
89             1;
90              
91             __END__