Profile of Plack/Request.pm

← Index
NYTProf Performance Profile «line view»
For script/ponapi
Run on Wed Feb 10 15:51:26 2016
Reported on Thu Feb 11 09:43:09 2016

Filename | /usr/local/share/perl/5.18.2/Plack/Request.pm
Statements | Executed 8909665 statements in 37.5s

Subroutines
Calls | P | F | Exclusive Time | Inclusive Time | Subroutine
--- | --- | --- | --- | --- | ---
200002 | 2 | 1 | 17.6s | 37.1s | Plack::Request::::headersPlack::Request::headers
100001 | 1 | 1 | 5.31s | 12.3s | Plack::Request::::_parse_queryPlack::Request::_parse_query
599517 | 4 | 1 | 3.54s | 4.53s | Plack::Request::::methodPlack::Request::method
3002136 | 2 | 1 | 1.71s | 1.71s | Plack::Request::::CORE:matchPlack::Request::CORE:match (opcode)
1299524 | 7 | 1 | 1.58s | 1.58s | Plack::Request::::envPlack::Request::env
200002 | 2 | 1 | 1.31s | 1.52s | Plack::Request::::content_lengthPlack::Request::content_length
100001 | 1 | 1 | 1.21s | 13.5s | Plack::Request::::query_parametersPlack::Request::query_parameters
904221 | 3 | 1 | 1.18s | 1.18s | Plack::Request::::CORE:substPlack::Request::CORE:subst (opcode)
100001 | 1 | 1 | 788ms | 788ms | Plack::Request::::newPlack::Request::new
100001 | 1 | 1 | 671ms | 735ms | Plack::Request::::request_uriPlack::Request::request_uri
100001 | 1 | 1 | 652ms | 719ms | Plack::Request::::path_infoPlack::Request::path_info
1 | 1 | 1 | 5.69ms | 5.86ms | Plack::Request::::BEGIN@7Plack::Request::BEGIN@7
1 | 1 | 1 | 3.90ms | 21.3ms | Plack::Request::::BEGIN@10Plack::Request::BEGIN@10
1 | 1 | 1 | 2.44ms | 2.72ms | Plack::Request::::BEGIN@9Plack::Request::BEGIN@9
1 | 1 | 1 | 304µs | 341µs | Plack::Request::::BEGIN@12Plack::Request::BEGIN@12
1 | 1 | 1 | 278µs | 2.30ms | Plack::Request::::BEGIN@13Plack::Request::BEGIN@13
1 | 1 | 1 | 18µs | 46µs | Plack::Request::::BEGIN@2Plack::Request::BEGIN@2
1 | 1 | 1 | 17µs | 17µs | Plack::Request::::BEGIN@4Plack::Request::BEGIN@4
1 | 1 | 1 | 17µs | 27µs | Plack::Request::::BEGIN@3Plack::Request::BEGIN@3
1 | 1 | 1 | 8µs | 8µs | Plack::Request::::BEGIN@8Plack::Request::BEGIN@8
1 | 1 | 1 | 7µs | 7µs | Plack::Request::::BEGIN@14Plack::Request::BEGIN@14
1 | 1 | 1 | 2µs | 2µs | Plack::Request::::BEGIN@15Plack::Request::BEGIN@15
0 | 0 | 0 | 0s | 0s | Plack::Request::::_make_uploadPlack::Request::_make_upload
0 | 0 | 0 | 0s | 0s | Plack::Request::::_parse_request_bodyPlack::Request::_parse_request_body
0 | 0 | 0 | 0s | 0s | Plack::Request::::_uri_basePlack::Request::_uri_base
0 | 0 | 0 | 0s | 0s | Plack::Request::::addressPlack::Request::address
0 | 0 | 0 | 0s | 0s | Plack::Request::::basePlack::Request::base
0 | 0 | 0 | 0s | 0s | Plack::Request::::bodyPlack::Request::body
0 | 0 | 0 | 0s | 0s | Plack::Request::::body_parametersPlack::Request::body_parameters
0 | 0 | 0 | 0s | 0s | Plack::Request::::contentPlack::Request::content
0 | 0 | 0 | 0s | 0s | Plack::Request::::content_encodingPlack::Request::content_encoding
0 | 0 | 0 | 0s | 0s | Plack::Request::::content_typePlack::Request::content_type
0 | 0 | 0 | 0s | 0s | Plack::Request::::cookiesPlack::Request::cookies
0 | 0 | 0 | 0s | 0s | Plack::Request::::headerPlack::Request::header
0 | 0 | 0 | 0s | 0s | Plack::Request::::inputPlack::Request::input
0 | 0 | 0 | 0s | 0s | Plack::Request::::loggerPlack::Request::logger
0 | 0 | 0 | 0s | 0s | Plack::Request::::new_responsePlack::Request::new_response
0 | 0 | 0 | 0s | 0s | Plack::Request::::paramPlack::Request::param
0 | 0 | 0 | 0s | 0s | Plack::Request::::parametersPlack::Request::parameters
0 | 0 | 0 | 0s | 0s | Plack::Request::::pathPlack::Request::path
0 | 0 | 0 | 0s | 0s | Plack::Request::::portPlack::Request::port
0 | 0 | 0 | 0s | 0s | Plack::Request::::protocolPlack::Request::protocol
0 | 0 | 0 | 0s | 0s | Plack::Request::::query_stringPlack::Request::query_string
0 | 0 | 0 | 0s | 0s | Plack::Request::::raw_bodyPlack::Request::raw_body
0 | 0 | 0 | 0s | 0s | Plack::Request::::refererPlack::Request::referer
0 | 0 | 0 | 0s | 0s | Plack::Request::::remote_hostPlack::Request::remote_host
0 | 0 | 0 | 0s | 0s | Plack::Request::::schemePlack::Request::scheme
0 | 0 | 0 | 0s | 0s | Plack::Request::::script_namePlack::Request::script_name
0 | 0 | 0 | 0s | 0s | Plack::Request::::securePlack::Request::secure
0 | 0 | 0 | 0s | 0s | Plack::Request::::sessionPlack::Request::session
0 | 0 | 0 | 0s | 0s | Plack::Request::::session_optionsPlack::Request::session_options
0 | 0 | 0 | 0s | 0s | Plack::Request::::uploadPlack::Request::upload
0 | 0 | 0 | 0s | 0s | Plack::Request::::uploadsPlack::Request::uploads
0 | 0 | 0 | 0s | 0s | Plack::Request::::uriPlack::Request::uri
0 | 0 | 0 | 0s | 0s | Plack::Request::::userPlack::Request::user
0 | 0 | 0 | 0s | 0s | Plack::Request::::user_agentPlack::Request::user_agent

Call graph for these subroutines as a Graphviz dot language file.

Line | State ments | Time on line | Calls | Time in subs | Code
--- | --- | --- | --- | --- | ---
1 |  |  |  |  | package Plack::Request;
2 | 2 | 42µs | 2 | 75µs | # spent 46µs (18+28) within Plack::Request::BEGIN@2 which was called: # once (18µs+28µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 2 use strict; # spent 46µs making 1 call to Plack::Request::BEGIN@2 # spent 28µs making 1 call to strict::import
3 | 2 | 38µs | 2 | 37µs | # spent 27µs (17+10) within Plack::Request::BEGIN@3 which was called: # once (17µs+10µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 3 use warnings; # spent 27µs making 1 call to Plack::Request::BEGIN@3 # spent 10µs making 1 call to warnings::import
4 | 2 | 86µs | 1 | 17µs | # spent 17µs within Plack::Request::BEGIN@4 which was called: # once (17µs+0s) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 4 use 5.008_001; # spent 17µs making 1 call to Plack::Request::BEGIN@4
5 | 1 | 500ns |  |  | our $VERSION = '1.0037';
6 |  |  |  |  |
7 | 2 | 175µs | 1 | 5.86ms | # spent 5.86ms (5.69+170µs) within Plack::Request::BEGIN@7 which was called: # once (5.69ms+170µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 7 use HTTP::Headers::Fast; # spent 5.86ms making 1 call to Plack::Request::BEGIN@7
8 | 2 | 33µs | 1 | 8µs | # spent 8µs within Plack::Request::BEGIN@8 which was called: # once (8µs+0s) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 8 use Carp (); # spent 8µs making 1 call to Plack::Request::BEGIN@8
9 | 2 | 159µs | 1 | 2.72ms | # spent 2.72ms (2.44+282µs) within Plack::Request::BEGIN@9 which was called: # once (2.44ms+282µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 9 use Hash::MultiValue; # spent 2.72ms making 1 call to Plack::Request::BEGIN@9
10 | 2 | 137µs | 1 | 21.3ms | # spent 21.3ms (3.90+17.4) within Plack::Request::BEGIN@10 which was called: # once (3.90ms+17.4ms) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 10 use HTTP::Body; # spent 21.3ms making 1 call to Plack::Request::BEGIN@10
11 |  |  |  |  |
12 | 2 | 76µs | 1 | 341µs | # spent 341µs (304+36) within Plack::Request::BEGIN@12 which was called: # once (304µs+36µs) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 12 use Plack::Request::Upload; # spent 341µs making 1 call to Plack::Request::BEGIN@12
13 | 2 | 70µs | 1 | 2.30ms | # spent 2.30ms (278µs+2.02) within Plack::Request::BEGIN@13 which was called: # once (278µs+2.02ms) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 13 use Stream::Buffered; # spent 2.30ms making 1 call to Plack::Request::BEGIN@13
14 | 2 | 20µs | 1 | 7µs | # spent 7µs within Plack::Request::BEGIN@14 which was called: # once (7µs+0s) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 14 use URI; # spent 7µs making 1 call to Plack::Request::BEGIN@14
15 | 2 | 1.48ms | 1 | 2µs | # spent 2µs within Plack::Request::BEGIN@15 which was called: # once (2µs+0s) by PONAPI::CLI::RunServer::BEGIN@4.20 at line 15 use URI::Escape (); # spent 2µs making 1 call to Plack::Request::BEGIN@15
16 |  |  |  |  |
17 |  |  |  |  | # spent 788ms within Plack::Request::new which was called 100001 times, avg 8µs/call: # 100001 times (788ms+0s) by PONAPI::Server::call at line 64 of lib/PONAPI/Server.pm, avg 8µs/call sub new {
18 | 100001 | 84.2ms |  |  | my($class, $env) = @_;
19 | 100001 | 152ms |  |  | Carp::croak(q{$env is required})
20 |  |  |  |  | unless defined $env && ref($env) eq 'HASH';
21 |  |  |  |  |
22 | 100001 | 846ms |  |  | bless { env => $env }, $class;
23 |  |  |  |  | }
24 |  |  |  |  |
25 | 1299524 | 5.11s |  |  | # spent 1.58s within Plack::Request::env which was called 1299524 times, avg 1µs/call: # 599517 times (986ms+0s) by Plack::Request::method at line 30, avg 2µs/call # 200002 times (213ms+0s) by Plack::Request::content_length at line 43, avg 1µs/call # 100001 times (98.5ms+0s) by Plack::Request::headers at line 123, avg 985ns/call # 100001 times (86.5ms+0s) by Plack::Request::query_parameters at line 80, avg 865ns/call # 100001 times (67.5ms+0s) by Plack::Request::path_info at line 34, avg 675ns/call # 100001 times (67.2ms+0s) by Plack::Request::_parse_query at line 87, avg 672ns/call # 100001 times (64.9ms+0s) by Plack::Request::request_uri at line 33, avg 649ns/call sub env { $_[0]->{env} }
26 |  |  |  |  |
27 |  |  |  |  | sub address { $_[0]->env->{REMOTE_ADDR} }
28 |  |  |  |  | sub remote_host { $_[0]->env->{REMOTE_HOST} }
29 |  |  |  |  | sub protocol { $_[0]->env->{SERVER_PROTOCOL} }
30 | 599517 | 3.44s | 599517 | 986ms | # spent 4.53s (3.54+986ms) within Plack::Request::method which was called 599517 times, avg 8µs/call: # 299514 times (1.30s+209ms) by PONAPI::Server::_is_get_like at line 99 of lib/PONAPI/Server.pm, avg 5µs/call # 100001 times (869ms+332ms) by PONAPI::Server::_ponapi_check_headers at line 201 of lib/PONAPI/Server.pm, avg 12µs/call # 100001 times (701ms+220ms) by PONAPI::Server::_ponapi_route_match at line 139 of lib/PONAPI/Server.pm, avg 9µs/call # 100001 times (673ms+224ms) by PONAPI::Server::call at line 78 of lib/PONAPI/Server.pm, avg 9µs/call sub method { $_[0]->env->{REQUEST_METHOD} } # spent 986ms making 599517 calls to Plack::Request::env, avg 2µs/call
31 |  |  |  |  | sub port { $_[0]->env->{SERVER_PORT} }
32 |  |  |  |  | sub user { $_[0]->env->{REMOTE_USER} }
33 | 100001 | 531ms | 100001 | 64.9ms | # spent 735ms (671+64.9) within Plack::Request::request_uri which was called 100001 times, avg 7µs/call: # 100001 times (671ms+64.9ms) by PONAPI::Server::_ponapi_params at line 120 of lib/PONAPI/Server.pm, avg 7µs/call sub request_uri { $_[0]->env->{REQUEST_URI} } # spent 64.9ms making 100001 calls to Plack::Request::env, avg 649ns/call
34 | 100001 | 550ms | 100001 | 67.5ms | # spent 719ms (652+67.5) within Plack::Request::path_info which was called 100001 times, avg 7µs/call: # 100001 times (652ms+67.5ms) by PONAPI::Server::_ponapi_route_match at line 143 of lib/PONAPI/Server.pm, avg 7µs/call sub path_info { $_[0]->env->{PATH_INFO} } # spent 67.5ms making 100001 calls to Plack::Request::env, avg 675ns/call
35 |  |  |  |  | sub path { $_[0]->env->{PATH_INFO} || '/' }
36 |  |  |  |  | sub query_string{ $_[0]->env->{QUERY_STRING} }
37 |  |  |  |  | sub script_name { $_[0]->env->{SCRIPT_NAME} }
38 |  |  |  |  | sub scheme { $_[0]->env->{'psgi.url_scheme'} }
39 |  |  |  |  | sub secure { $_[0]->scheme eq 'https' }
40 |  |  |  |  | sub body { $_[0]->env->{'psgi.input'} }
41 |  |  |  |  | sub input { $_[0]->env->{'psgi.input'} }
42 |  |  |  |  |
43 | 200002 | 1.27s | 200002 | 213ms | # spent 1.52s (1.31+213ms) within Plack::Request::content_length which was called 200002 times, avg 8µs/call: # 100001 times (719ms+98.5ms) by PONAPI::Server::_ponapi_check_headers at line 208 of lib/PONAPI/Server.pm, avg 8µs/call # 100001 times (586ms+115ms) by PONAPI::Server::_ponapi_data at line 291 of lib/PONAPI/Server.pm, avg 7µs/call sub content_length { $_[0]->env->{CONTENT_LENGTH} } # spent 213ms making 200002 calls to Plack::Request::env, avg 1µs/call
44 |  |  |  |  | sub content_type { $_[0]->env->{CONTENT_TYPE} }
45 |  |  |  |  |
46 |  |  |  |  | sub session { $_[0]->env->{'psgix.session'} }
47 |  |  |  |  | sub session_options { $_[0]->env->{'psgix.session.options'} }
48 |  |  |  |  | sub logger { $_[0]->env->{'psgix.logger'} }
49 |  |  |  |  |
50 |  |  |  |  | sub cookies {
51 |  |  |  |  | my $self = shift;
52 |  |  |  |  |
53 |  |  |  |  | return {} unless $self->env->{HTTP_COOKIE};
54 |  |  |  |  |
55 |  |  |  |  | # HTTP_COOKIE hasn't changed: reuse the parsed cookie
56 |  |  |  |  | if ( $self->env->{'plack.cookie.parsed'}
57 |  |  |  |  | && $self->env->{'plack.cookie.string'} eq $self->env->{HTTP_COOKIE}) {
58 |  |  |  |  | return $self->env->{'plack.cookie.parsed'};
59 |  |  |  |  | }
60 |  |  |  |  |
61 |  |  |  |  | $self->env->{'plack.cookie.string'} = $self->env->{HTTP_COOKIE};
62 |  |  |  |  |
63 |  |  |  |  | my %results;
64 |  |  |  |  | my @pairs = grep m/=/, split "[;,] ?", $self->env->{'plack.cookie.string'};
65 |  |  |  |  | for my $pair ( @pairs ) {
66 |  |  |  |  | # trim leading trailing whitespace
67 |  |  |  |  | $pair =~ s/^\s+//; $pair =~ s/\s+$//;
68 |  |  |  |  |
69 |  |  |  |  | my ($key, $value) = map URI::Escape::uri_unescape($_), split( "=", $pair, 2 );
70 |  |  |  |  |
71 |  |  |  |  | # Take the first one like CGI.pm or rack do
72 |  |  |  |  | $results{$key} = $value unless exists $results{$key};
73 |  |  |  |  | }
74 |  |  |  |  |
75 |  |  |  |  | $self->env->{'plack.cookie.parsed'} = \%results;
76 |  |  |  |  | }
77 |  |  |  |  |
78 |  |  |  |  | # spent 13.5s (1.21+12.3) within Plack::Request::query_parameters which was called 100001 times, avg 135µs/call: # 100001 times (1.21s+12.3s) by PONAPI::Server::_ponapi_query_params at line 240 of lib/PONAPI/Server.pm, avg 135µs/call sub query_parameters {
79 | 100001 | 50.0ms |  |  | my $self = shift;
80 | 100001 | 876ms | 200002 | 12.3s | $self->env->{'plack.request.query'} ||= $self->_parse_query; # spent 12.3s making 100001 calls to Plack::Request::_parse_query, avg 123µs/call # spent 86.5ms making 100001 calls to Plack::Request::env, avg 865ns/call
81 |  |  |  |  | }
82 |  |  |  |  |
83 |  |  |  |  | # spent 12.3s (5.31+6.94) within Plack::Request::_parse_query which was called 100001 times, avg 123µs/call: # 100001 times (5.31s+6.94s) by Plack::Request::query_parameters at line 80, avg 123µs/call sub _parse_query {
84 | 100001 | 43.6ms |  |  | my $self = shift;
85 |  |  |  |  |
86 | 100001 | 32.6ms |  |  | my @query;
87 | 100001 | 189ms | 100001 | 67.2ms | my $query_string = $self->env->{QUERY_STRING}; # spent 67.2ms making 100001 calls to Plack::Request::env, avg 672ns/call
88 | 100001 | 112ms |  |  | if (defined $query_string) {
89 | 100001 | 625ms | 100001 | 133ms | $query_string =~ s/\A[&;]+//; # spent 133ms making 100001 calls to Plack::Request::CORE:subst, avg 1µs/call
90 | 204214 | 725ms | 204214 | 71.7ms | @query = # spent 71.7ms making 204214 calls to Plack::Request::CORE:subst, avg 351ns/call
91 | 306321 | 982ms | 306321 | 1.40s | map { s/\+/ /g; URI::Escape::uri_unescape($_) } # spent 1.27s making 204214 calls to URI::Escape::uri_unescape, avg 6µs/call # spent 123ms making 102107 calls to Plack::Request::CORE:match, avg 1µs/call
92 | 100001 | 519ms |  |  | map { /=/ ? split(/=/, $_, 2) : ($_ => '')}
93 |  |  |  |  | split(/[&;]+/, $query_string);
94 |  |  |  |  | }
95 |  |  |  |  |
96 | 100001 | 1.09s | 100001 | 3.76s | Hash::MultiValue->new(@query); # spent 3.76s making 100001 calls to Hash::MultiValue::new, avg 38µs/call
97 |  |  |  |  | }
98 |  |  |  |  |
99 |  |  |  |  | sub content {
100 |  |  |  |  | my $self = shift;
101 |  |  |  |  |
102 |  |  |  |  | unless ($self->env->{'psgix.input.buffered'}) {
103 |  |  |  |  | $self->_parse_request_body;
104 |  |  |  |  | }
105 |  |  |  |  |
106 |  |  |  |  | my $fh = $self->input or return '';
107 |  |  |  |  | my $cl = $self->env->{CONTENT_LENGTH} or return '';
108 |  |  |  |  |
109 |  |  |  |  | $fh->seek(0, 0); # just in case middleware/apps read it without seeking back
110 |  |  |  |  | $fh->read(my($content), $cl, 0);
111 |  |  |  |  | $fh->seek(0, 0);
112 |  |  |  |  |
113 |  |  |  |  | return $content;
114 |  |  |  |  | }
115 |  |  |  |  |
116 |  |  |  |  | sub raw_body { $_[0]->content }
117 |  |  |  |  |
118 |  |  |  |  | # XXX you can mutate headers with ->headers but it's not written through to the env
119 |  |  |  |  |
120 |  |  |  |  | # spent 37.1s (17.6+19.5) within Plack::Request::headers which was called 200002 times, avg 186µs/call: # 100001 times (17.3s+19.5s) by PONAPI::Server::_ponapi_check_headers at line 218 of lib/PONAPI/Server.pm, avg 368µs/call # 100001 times (280ms+0s) by PONAPI::Server::_ponapi_query_params at line 242 of lib/PONAPI/Server.pm, avg 3µs/call sub headers {
121 | 200002 | 105ms |  |  | my $self = shift;
122 | 200002 | 521ms |  |  | if (!defined $self->{headers}) {
123 | 100001 | 189ms | 100001 | 98.5ms | my $env = $self->env; # spent 98.5ms making 100001 calls to Plack::Request::env, avg 985ns/call
124 | 600006 | 3.52s | 600006 | 973ms | $self->{headers} = HTTP::Headers::Fast->new( # spent 973ms making 600006 calls to Plack::Request::CORE:subst, avg 2µs/call
125 |  |  |  |  | map {
126 | 2900029 | 11.2s | 2900029 | 1.58s | (my $field = $_) =~ s/^HTTPS?_//; # spent 1.58s making 2900029 calls to Plack::Request::CORE:match, avg 546ns/call
127 | 600006 | 975ms |  |  | ( $field => $env->{$_} );
128 |  |  |  |  | }
129 | 100001 | 2.86s | 100001 | 16.9s | grep { /^(?:HTTP|CONTENT)/i } keys %$env # spent 16.9s making 100001 calls to HTTP::Headers::Fast::new, avg 169µs/call
130 |  |  |  |  | );
131 |  |  |  |  | }
132 | 200002 | 930ms |  |  | $self->{headers};
133 |  |  |  |  | }
134 |  |  |  |  |
135 |  |  |  |  | sub content_encoding { shift->headers->content_encoding(@_) }
136 |  |  |  |  | sub header { shift->headers->header(@_) }
137 |  |  |  |  | sub referer { shift->headers->referer(@_) }
138 |  |  |  |  | sub user_agent { shift->headers->user_agent(@_) }
139 |  |  |  |  |
140 |  |  |  |  | sub body_parameters {
141 |  |  |  |  | my $self = shift;
142 |  |  |  |  |
143 |  |  |  |  | unless ($self->env->{'plack.request.body'}) {
144 |  |  |  |  | $self->_parse_request_body;
145 |  |  |  |  | }
146 |  |  |  |  |
147 |  |  |  |  | return $self->env->{'plack.request.body'};
148 |  |  |  |  | }
149 |  |  |  |  |
150 |  |  |  |  | # contains body + query
151 |  |  |  |  | sub parameters {
152 |  |  |  |  | my $self = shift;
153 |  |  |  |  |
154 |  |  |  |  | $self->env->{'plack.request.merged'} ||= do {
155 |  |  |  |  | my $query = $self->query_parameters;
156 |  |  |  |  | my $body = $self->body_parameters;
157 |  |  |  |  | Hash::MultiValue->new($query->flatten, $body->flatten);
158 |  |  |  |  | };
159 |  |  |  |  | }
160 |  |  |  |  |
161 |  |  |  |  | sub uploads {
162 |  |  |  |  | my $self = shift;
163 |  |  |  |  |
164 |  |  |  |  | if ($self->env->{'plack.request.upload'}) {
165 |  |  |  |  | return $self->env->{'plack.request.upload'};
166 |  |  |  |  | }
167 |  |  |  |  |
168 |  |  |  |  | $self->_parse_request_body;
169 |  |  |  |  | return $self->env->{'plack.request.upload'};
170 |  |  |  |  | }
171 |  |  |  |  |
172 |  |  |  |  | sub param {
173 |  |  |  |  | my $self = shift;
174 |  |  |  |  |
175 |  |  |  |  | return keys %{ $self->parameters } if @_ == 0;
176 |  |  |  |  |
177 |  |  |  |  | my $key = shift;
178 |  |  |  |  | return $self->parameters->{$key} unless wantarray;
179 |  |  |  |  | return $self->parameters->get_all($key);
180 |  |  |  |  | }
181 |  |  |  |  |
182 |  |  |  |  | sub upload {
183 |  |  |  |  | my $self = shift;
184 |  |  |  |  |
185 |  |  |  |  | return keys %{ $self->uploads } if @_ == 0;
186 |  |  |  |  |
187 |  |  |  |  | my $key = shift;
188 |  |  |  |  | return $self->uploads->{$key} unless wantarray;
189 |  |  |  |  | return $self->uploads->get_all($key);
190 |  |  |  |  | }
191 |  |  |  |  |
192 |  |  |  |  | sub uri {
193 |  |  |  |  | my $self = shift;
194 |  |  |  |  |
195 |  |  |  |  | my $base = $self->_uri_base;
196 |  |  |  |  |
197 |  |  |  |  | # We have to escape back PATH_INFO in case they include stuff like
198 |  |  |  |  | # ? or # so that the URI parser won't be tricked. However we should
199 |  |  |  |  | # preserve '/' since encoding them into %2f doesn't make sense.
200 |  |  |  |  | # This means when a request like /foo%2fbar comes in, we recognize
201 |  |  |  |  | # it as /foo/bar which is not ideal, but that's how the PSGI PATH_INFO
202 |  |  |  |  | # spec goes and we can't do anything about it. See PSGI::FAQ for details.
203 |  |  |  |  |
204 |  |  |  |  | # See RFC 3986 before modifying.
205 |  |  |  |  | my $path_escape_class = q{^/;:@&=A-Za-z0-9\$_.+!*'(),-};
206 |  |  |  |  |
207 |  |  |  |  | my $path = URI::Escape::uri_escape($self->env->{PATH_INFO} || '', $path_escape_class);
208 |  |  |  |  | $path .= '?' . $self->env->{QUERY_STRING}
209 |  |  |  |  | if defined $self->env->{QUERY_STRING} && $self->env->{QUERY_STRING} ne '';
210 |  |  |  |  |
211 |  |  |  |  | $base =~ s!/$!! if $path =~ m!^/!;
212 |  |  |  |  |
213 |  |  |  |  | return URI->new($base . $path)->canonical;
214 |  |  |  |  | }
215 |  |  |  |  |
216 |  |  |  |  | sub base {
217 |  |  |  |  | my $self = shift;
218 |  |  |  |  | URI->new($self->_uri_base)->canonical;
219 |  |  |  |  | }
220 |  |  |  |  |
221 |  |  |  |  | sub _uri_base {
222 |  |  |  |  | my $self = shift;
223 |  |  |  |  |
224 |  |  |  |  | my $env = $self->env;
225 |  |  |  |  |
226 |  |  |  |  | my $uri = ($env->{'psgi.url_scheme'} || "http") .
227 |  |  |  |  | "://" .
228 |  |  |  |  | ($env->{HTTP_HOST} || (($env->{SERVER_NAME} || "") . ":" . ($env->{SERVER_PORT} || 80))) .
229 |  |  |  |  | ($env->{SCRIPT_NAME} || '/');
230 |  |  |  |  |
231 |  |  |  |  | return $uri;
232 |  |  |  |  | }
233 |  |  |  |  |
234 |  |  |  |  | sub new_response {
235 |  |  |  |  | my $self = shift;
236 |  |  |  |  | require Plack::Response;
237 |  |  |  |  | Plack::Response->new(@_);
238 |  |  |  |  | }
239 |  |  |  |  |
240 |  |  |  |  | sub _parse_request_body {
241 |  |  |  |  | my $self = shift;
242 |  |  |  |  |
243 |  |  |  |  | my $ct = $self->env->{CONTENT_TYPE};
244 |  |  |  |  | my $cl = $self->env->{CONTENT_LENGTH};
245 |  |  |  |  | if (!$ct && !$cl) {
246 |  |  |  |  | # No Content-Type nor Content-Length -> GET/HEAD
247 |  |  |  |  | $self->env->{'plack.request.body'} = Hash::MultiValue->new;
248 |  |  |  |  | $self->env->{'plack.request.upload'} = Hash::MultiValue->new;
249 |  |  |  |  | return;
250 |  |  |  |  | }
251 |  |  |  |  |
252 |  |  |  |  | my $body = HTTP::Body->new($ct, $cl);
253 |  |  |  |  |
254 |  |  |  |  | # HTTP::Body will create temporary files in case there was an
255 |  |  |  |  | # upload. Those temporary files can be cleaned up by telling
256 |  |  |  |  | # HTTP::Body to do so. It will run the cleanup when the request
257 |  |  |  |  | # env is destroyed. That the object will not go out of scope by
258 |  |  |  |  | # the end of this sub we will store a reference here.
259 |  |  |  |  | $self->env->{'plack.request.http.body'} = $body;
260 |  |  |  |  | $body->cleanup(1);
261 |  |  |  |  |
262 |  |  |  |  | my $input = $self->input;
263 |  |  |  |  |
264 |  |  |  |  | my $buffer;
265 |  |  |  |  | if ($self->env->{'psgix.input.buffered'}) {
266 |  |  |  |  | # Just in case if input is read by middleware/apps beforehand
267 |  |  |  |  | $input->seek(0, 0);
268 |  |  |  |  | } else {
269 |  |  |  |  | $buffer = Stream::Buffered->new($cl);
270 |  |  |  |  | }
271 |  |  |  |  |
272 |  |  |  |  | my $spin = 0;
273 |  |  |  |  | while ($cl) {
274 |  |  |  |  | $input->read(my $chunk, $cl < 8192 ? $cl : 8192);
275 |  |  |  |  | my $read = length $chunk;
276 |  |  |  |  | $cl -= $read;
277 |  |  |  |  | $body->add($chunk);
278 |  |  |  |  | $buffer->print($chunk) if $buffer;
279 |  |  |  |  |
280 |  |  |  |  | if ($read == 0 && $spin++ > 2000) {
281 |  |  |  |  | Carp::croak "Bad Content-Length: maybe client disconnect? ($cl bytes remaining)";
282 |  |  |  |  | }
283 |  |  |  |  | }
284 |  |  |  |  |
285 |  |  |  |  | if ($buffer) {
286 |  |  |  |  | $self->env->{'psgix.input.buffered'} = 1;
287 |  |  |  |  | $self->env->{'psgi.input'} = $buffer->rewind;
288 |  |  |  |  | } else {
289 |  |  |  |  | $input->seek(0, 0);
290 |  |  |  |  | }
291 |  |  |  |  |
292 |  |  |  |  | $self->env->{'plack.request.body'} = Hash::MultiValue->from_mixed($body->param);
293 |  |  |  |  |
294 |  |  |  |  | my @uploads = Hash::MultiValue->from_mixed($body->upload)->flatten;
295 |  |  |  |  | my @obj;
296 |  |  |  |  | while (my($k, $v) = splice @uploads, 0, 2) {
297 |  |  |  |  | push @obj, $k, $self->_make_upload($v);
298 |  |  |  |  | }
299 |  |  |  |  |
300 |  |  |  |  | $self->env->{'plack.request.upload'} = Hash::MultiValue->new(@obj);
301 |  |  |  |  |
302 |  |  |  |  | 1;
303 |  |  |  |  | }
304 |  |  |  |  |
305 |  |  |  |  | sub _make_upload {
306 |  |  |  |  | my($self, $upload) = @_;
307 |  |  |  |  | my %copy = %$upload;
308 |  |  |  |  | $copy{headers} = HTTP::Headers::Fast->new(%{$upload->{headers}});
309 |  |  |  |  | Plack::Request::Upload->new(%copy);
310 |  |  |  |  | }
311 |  |  |  |  |
312 | 1 | 2µs |  |  | 1;
313 |  |  |  |  | __END__
|  |  |  |  | # spent 1.71s within Plack::Request::CORE:match which was called 3002136 times, avg 568ns/call: # 2900029 times (1.58s+0s) by Plack::Request::headers at line 126, avg 546ns/call # 102107 times (123ms+0s) by Plack::Request::_parse_query at line 91, avg 1µs/call sub Plack::Request::CORE:match; # opcode
|  |  |  |  | # spent 1.18s within Plack::Request::CORE:subst which was called 904221 times, avg 1µs/call: # 600006 times (973ms+0s) by Plack::Request::headers at line 124, avg 2µs/call # 204214 times (71.7ms+0s) by Plack::Request::_parse_query at line 90, avg 351ns/call # 100001 times (133ms+0s) by Plack::Request::_parse_query at line 89, avg 1µs/call sub Plack::Request::CORE:subst; # opcode