← Index
NYTProf Performance Profile   « block view • line view • sub view »
For /usr/local/src/github.com/foswiki/core/bin/view
  Run on Sun Dec 4 17:17:59 2011
Reported on Sun Dec 4 17:26:40 2011

Filename/usr/local/src/github.com/foswiki/core/lib/Foswiki/Response.pm
StatementsExecuted 125 statements in 3.86ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
611179µs247µsFoswiki::Response::::getHeaderFoswiki::Response::getHeader
111166µs221µsFoswiki::Response::::setDefaultHeadersFoswiki::Response::setDefaultHeaders
111132µs397µsFoswiki::Response::::printHeadersFoswiki::Response::printHeaders
222105µs109µsFoswiki::Response::::bodyFoswiki::Response::body
363195µs95µsFoswiki::Response::::CORE:substcontFoswiki::Response::CORE:substcont (opcode)
21194µs135µsFoswiki::Response::::pushHeaderFoswiki::Response::pushHeader
11179µs153µsFoswiki::Response::::printFoswiki::Response::print
123164µs64µsFoswiki::Response::::CORE:substFoswiki::Response::CORE:subst (opcode)
43340µs40µsFoswiki::Response::::cookiesFoswiki::Response::cookies
22232µs32µsFoswiki::Response::::statusFoswiki::Response::status
11128µs35µsFoswiki::Response::::BEGIN@19Foswiki::Response::BEGIN@19
11123µs23µsFoswiki::Response::::newFoswiki::Response::new
11116µs33µsFoswiki::Response::::BEGIN@20Foswiki::Response::BEGIN@20
11115µs51µsFoswiki::Response::::BEGIN@21Foswiki::Response::BEGIN@21
11110µs10µsFoswiki::Response::::outputHasStartedFoswiki::Response::outputHasStarted
1119µs9µsFoswiki::Response::::BEGIN@23Foswiki::Response::BEGIN@23
0000s0sFoswiki::Response::::charsetFoswiki::Response::charset
0000s0sFoswiki::Response::::deleteHeaderFoswiki::Response::deleteHeader
0000s0sFoswiki::Response::::headerFoswiki::Response::header
0000s0sFoswiki::Response::::headersFoswiki::Response::headers
0000s0sFoswiki::Response::::redirectFoswiki::Response::redirect
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2
3=begin TML
4
5---+!! package Foswiki::Response
6
7Class to encapsulate response data.
8
9Fields:
10 * =status= - response status
11 * =headers= - hashref to response headers
12 * =body= - response body
13 * =cookies= - hashref to response cookies
14
15=cut
16
17package Foswiki::Response;
18
19245µs241µs
# spent 35µs (28+7) within Foswiki::Response::BEGIN@19 which was called: # once (28µs+7µs) by Foswiki::Engine::CGI::BEGIN@24 at line 19
use strict;
# spent 35µs making 1 call to Foswiki::Response::BEGIN@19 # spent 7µs making 1 call to strict::import
20241µs250µs
# spent 33µs (16+17) within Foswiki::Response::BEGIN@20 which was called: # once (16µs+17µs) by Foswiki::Engine::CGI::BEGIN@24 at line 20
use warnings;
# spent 33µs making 1 call to Foswiki::Response::BEGIN@20 # spent 17µs making 1 call to warnings::import
21242µs286µs
# spent 51µs (15+36) within Foswiki::Response::BEGIN@21 which was called: # once (15µs+36µs) by Foswiki::Engine::CGI::BEGIN@24 at line 21
use Assert;
# spent 51µs making 1 call to Foswiki::Response::BEGIN@21 # spent 36µs making 1 call to Assert::import
22
2322.69ms19µs
# spent 9µs within Foswiki::Response::BEGIN@23 which was called: # once (9µs+0s) by Foswiki::Engine::CGI::BEGIN@24 at line 23
use CGI::Util ();
# spent 9µs making 1 call to Foswiki::Response::BEGIN@23
24
25=begin TML
26
27---++ ClassMethod new() -> $response
28
29Constructs a Foswiki::Response object.
30
31=cut
32
33
# spent 23µs within Foswiki::Response::new which was called: # once (23µs+0s) by Foswiki::new at line 1672 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm
sub new {
34428µs my $proto = shift;
35 my $class = ref($proto) || $proto;
36 my $this = {
37
38#status needs to default to 'unset' to the web server can set the status to whatever it needs (think basic auth, or other magics)
39 status => undef,
40 headers => {},
41 body => undef,
42 charset => $Foswiki::cfg{Site}{CharSet},
43 cookies => [],
44 outputHasStarted => 0,
45 };
46
47 return bless $this, $class;
48}
49
50=begin TML
51
52---++ ObjectMethod status( $status ) -> $status
53
54Gets/Sets response status.
55 * =$status= is a three digit code, optionally followed by a status string
56
57=cut
58
59
# spent 32µs within Foswiki::Response::status which was called 2 times, avg 16µs/call: # once (17µs+0s) by Foswiki::Response::printHeaders at line 279 # once (15µs+0s) by Foswiki::UI::__ANON__[/usr/local/src/github.com/foswiki/core/lib/Foswiki/UI.pm:318] at line 314 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/UI.pm
sub status {
60626µs my ( $this, $status ) = @_;
61 if ($status) {
62 ASSERT( !$this->{outputHasStarted}, 'Too late to change status' )
63 if DEBUG;
64 $this->{status} = $status =~ /^\d{3}/ ? $status : undef;
65 }
66 return $this->{status};
67}
68
69=begin TML
70
71---++ ObjectMethod charset([$charset]) -> $charset
72
73Gets/Sets response charset. If not defined, defaults to ISO-8859-1,
74just like CGI.pm
75
76=cut
77
78sub charset {
79 return @_ == 1 ? $_[0]->{charset} : ( $_[0]->{charset} = $_[1] );
80}
81
82=begin TML
83
84---++ ObjectMethod header(-type => $type,
85 -status => $status,
86 -cookie => $cookie || \@cookies,
87 -attachment => $attachName,
88 -charset => $charset,
89 -expires => $expires,
90 -HeaderN => ValueN )
91
92Sets response header. Resonably compatible with CGI.
93Doesn't support -nph, -target and -p3p.
94
95=cut
96
97sub header {
98 my ( $this, @p ) = @_;
99 my (@header);
100
101 ASSERT( !$this->{outputHasStarted}, 'Too late to change headers' ) if DEBUG;
102
103 # Ugly hack to avoid html escape in CGI::Util::rearrange
104 local $CGI::Q = { escape => 0 };
105
106 # SMELL: CGI::Util is documented as not having any public subroutines
107 my ( $type, $status, $cookie, $charset, $expires, @other ) =
108 CGI::Util::rearrange(
109 [
110 [ 'TYPE', 'CONTENT_TYPE', 'CONTENT-TYPE' ], 'STATUS',
111 [ 'COOKIE', 'COOKIES' ], 'CHARSET',
112 'EXPIRES',
113 ],
114 @p
115 );
116
117 if ( defined $charset ) {
118 $this->charset($charset);
119 }
120 else {
121 $charset = $this->charset;
122 }
123
124 foreach (@other) {
125
126 # Don't use \s because of perl bug 21951
127 next unless my ( $header, $value ) = /([^ \r\n\t=]+)=\"?(.+?)\"?$/;
128
129 $header = lc($header);
130 $header =~ s/\b(\w)/\u$1/g;
131 if ( exists $this->{headers}->{$header} ) {
132 if ( ref $this->{headers}->{$header} ) {
133 push @{ $this->{headers}->{$header} }, $value;
134 }
135 else {
136 $this->{headers}->{$header} =
137 [ $this->{headers}->{$header}, $value ];
138 }
139 }
140 else {
141 $this->{headers}->{$header} = $value;
142 }
143 }
144
145 $type ||= 'text/html' unless defined($type);
146 $type .= "; charset=$charset"
147 if $type ne ''
148 and $type =~ m!^text/!
149 and $type !~ /\bcharset\b/
150 and $charset ne '';
151
152 if ($status) {
153 $this->{headers}->{Status} = $status;
154 $this->status($status);
155 }
156
157 # push all the cookies -- there may be several
158 if ($cookie) {
159 my @cookies = ref($cookie) eq 'ARRAY' ? @$cookie : ($cookie);
160 $this->cookies( \@cookies );
161 }
162 $this->{headers}->{Expires} = CGI::Util::expires( $expires, 'http' )
163 if ( defined $expires );
164 $this->{headers}->{Date} = CGI::Util::expires( 0, 'http' )
165 if defined $expires || $cookie;
166
167 $this->{headers}->{'Content-Type'} = $type if $type ne '';
168}
169
170=begin TML
171
172---++ ObjectMethod headers( { ... } ) -> $headersHashRef
173
174Gets/Sets all response headers. Keys are headers name and values
175are scalars for single-valued headers or arrayref for multivalued ones.
176
177=cut
178
179sub headers {
180 my ( $this, $hdr ) = @_;
181 if ($hdr) {
182 ASSERT( !$this->{outputHasStarted}, 'Too late to change headers' )
183 if DEBUG;
184 my %headers = ();
185 while ( my ( $key, $value ) = each %$hdr ) {
186 $key =~ s/(?:^|(?<=-))(.)([^-]*)/\u$1\L$2\E/g;
187 $headers{$key} = $value;
188 }
189 $headers{Expires} = CGI::Util::expires( $headers{Expires}, 'http' )
190 if defined $headers{Expires};
191 $headers{Date} = CGI::Util::expires( 0, 'http' )
192 if defined $headers{'Set-Cookie'} || defined $headers{Expires};
193 if ( defined $headers{'Set-Cookie'} ) {
194 my @cookies =
195 ref( $headers{'Set-Cookie'} ) eq 'ARRAY'
196 ? @{ $headers{'Set-Cookie'} }
197 : ( $headers{'Set-Cookie'} );
198 $this->cookies( \@cookies );
199 }
200 $this->status( $headers{Status} ) if defined $headers{Status};
201 $this->{headers} = \%headers;
202 }
203 return $this->{headers};
204}
205
206=begin TML
207
208---++ ObjectMethod getHeader( [ $name ] ) -> $value
209
210If called without parameters returns all present header names,
211otherwise returns a list (maybe with a single element) of values
212associated with $name.
213
214=cut
215
216
# spent 247µs (179+69) within Foswiki::Response::getHeader which was called 6 times, avg 41µs/call: # 6 times (179µs+69µs) by Foswiki::Response::printHeaders at line 282, avg 41µs/call
sub getHeader {
21724202µs my ( $this, $hdr ) = @_;
218 return keys %{ $this->{headers} } unless $hdr;
2192469µs $hdr =~ s/(?:^|(?<=-))(.)([^-]*)/\u$1\L$2\E/g;
# spent 43µs making 18 calls to Foswiki::Response::CORE:substcont, avg 2µs/call # spent 26µs making 6 calls to Foswiki::Response::CORE:subst, avg 4µs/call
2201254µs if ( exists $this->{headers}->{$hdr} ) {
221 my $value = $this->{headers}->{$hdr};
222 return ref $value ? @$value : ($value);
223 }
224 else {
225 return;
226 }
227}
228
229=begin TML
230
231---++ ObjectMethod setDefaultHeaders( { $name => $value, ... } )
232
233Sets the header corresponding to the key => value pairs passed in the
234hash, if the key doesn't already exist, otherwise does nothing.
235This ensures some default values are entered, but they can be overridden
236by plugins or other parts in the code.
237
238=cut
239
240
# spent 221µs (166+55) within Foswiki::Response::setDefaultHeaders which was called: # once (166µs+55µs) by Foswiki::generateHTTPHeaders at line 1001 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm
sub setDefaultHeaders {
241450µs my ( $this, $hopt ) = @_;
242 return unless $hopt && keys %$hopt;
2438155µs while ( my ( $hdr, $value ) = each %$hopt ) {
2441655µs $hdr =~ s/(?:^|(?<=-))(.)([^-]*)/\u$1\L$2\E/g;
# spent 33µs making 12 calls to Foswiki::Response::CORE:substcont, avg 3µs/call # spent 22µs making 4 calls to Foswiki::Response::CORE:subst, avg 6µs/call
245820µs unless ( exists $this->{headers}->{$hdr} ) {
246 if ( $hdr eq 'Status' ) {
247 $this->status($hdr);
248 }
249 elsif ( $hdr eq 'Expires' ) {
250 $value = CGI::Util::expires( $value, 'http' );
251 }
252 elsif ( $hdr eq 'Set-Cookie' ) {
253 my @cookies = ref($value) eq 'ARRAY' ? @$value : ($value);
254 $this->cookies( \@cookies );
255 }
256 $this->{headers}->{$hdr} = $value;
257 }
258 }
259 $this->{headers}{Date} = CGI::Util::expires( 0, 'http' )
260 if !exists $this->{headers}{Date}
261 && ( defined $this->{headers}{Expires}
262 || defined $this->{headers}{'Set-Cookie'} );
263}
264
265=begin TML
266
267---++ ObjectMethod printHeaders()
268
269Return a string of all headers, separated by CRLF
270
271=cut
272
273
# spent 397µs (132+265) within Foswiki::Response::printHeaders which was called: # once (132µs+265µs) by Foswiki::Engine::CGI::finalizeHeaders at line 195 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Engine/CGI.pm
sub printHeaders {
274743µs my ($this) = shift;
275 my $CRLF = "\x0D\x0A";
276 my $hdr = '';
277
278 # make sure we always generate a status for the response
279117µs $this->{headers}->{Status} = $this->status()
# spent 17µs making 1 call to Foswiki::Response::status
280 if ( $this->status() && !defined( $this->headers->{Status} ) );
28112µs foreach my $header ( keys %{ $this->{headers} } ) {
282687µs6247µs $hdr .= $header . ': ' . $_ . $CRLF foreach $this->getHeader($header);
# spent 247µs making 6 calls to Foswiki::Response::getHeader, avg 41µs/call
283 }
284 $hdr .= $CRLF;
285 return $hdr;
286}
287
288=begin TML
289
290---++ ObjectMethod deleteHeader($h1, $h2, ...)
291
292Deletes headers whose names are passed.
293
294=cut
295
296sub deleteHeader {
297 my $this = shift;
298
299 ASSERT( !$this->{outputHasStarted}, 'Too late to change headers' ) if DEBUG;
300
301 foreach (@_) {
302 ( my $hdr = $_ ) =~ s/(?:^|(?<=-))(.)([^-]*)/\u$1\L$2\E/g;
303 delete $this->{headers}->{$hdr};
304 }
305}
306
307=begin TML
308
309---++ ObjectMethod pushHeader( $name, $value )
310
311Adds $value to list of values associated with header $name.
312
313=cut
314
315
# spent 135µs (94+42) within Foswiki::Response::pushHeader which was called 2 times, avg 68µs/call: # 2 times (94µs+42µs) by Foswiki::Engine::finalizeCookies at line 379 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Engine.pm, avg 68µs/call
sub pushHeader {
31610113µs my ( $this, $hdr, $value ) = @_;
317
31828µs ASSERT( !$this->{outputHasStarted}, 'Too late to change headers' ) if DEBUG;
# spent 8µs making 2 calls to Assert::ASSERTS_OFF, avg 4µs/call
319
320834µs $hdr =~ s/(?:^|(?<=-))(.)([^-]*)/\u$1\L$2\E/g;
# spent 19µs making 6 calls to Foswiki::Response::CORE:substcont, avg 3µs/call # spent 16µs making 2 calls to Foswiki::Response::CORE:subst, avg 8µs/call
321 my $cur = $this->{headers}->{$hdr};
32228µs if ($cur) {
32314µs if ( ref $cur ) {
324 push @{ $this->{headers}->{$hdr} }, $value;
325 }
326 else {
327 $this->{headers}->{$hdr} = [ $cur, $value ];
328 }
329 }
330 else {
331 $this->{headers}->{$hdr} = $value;
332 }
333}
334
335=begin TML
336
337---++ ObjectMethod cookies( [ \@cookies ] ) -> @cookies
338
339Gets/Sets response cookies. Parameter, if passed, *must* be an arrayref.
340
341Elements may be CGI::Cookie objects or raw cookie strings.
342
343WARNING: cookies set this way are *not* passed in redirects.
344
345=cut
346
347
# spent 40µs within Foswiki::Response::cookies which was called 4 times, avg 10µs/call: # 2 times (21µs+0s) by Foswiki::writeCompletePage at line 763 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm, avg 10µs/call # once (10µs+0s) by Foswiki::LoginManager::_addSessionCookieToResponse at line 839 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/LoginManager.pm # once (9µs+0s) by Foswiki::Engine::finalizeCookies at line 379 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Engine.pm
sub cookies {
348848µs return @_ == 1 ? @{ $_[0]->{cookies} } : @{ $_[0]->{cookies} = $_[1] };
349}
350
351=begin TML
352
353---++ ObjectMethod body( [ $body ] ) -> $body
354
355Gets/Sets response body. Note: do not use this method for output, use
356=print= instead.
357
358=cut
359
360
# spent 109µs (105+4) within Foswiki::Response::body which was called 2 times, avg 55µs/call: # once (71µs+4µs) by Foswiki::Response::print at line 424 # once (35µs+0s) by Foswiki::Engine::finalizeBody at line 396 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Engine.pm
sub body {
361676µs my ( $this, $body ) = @_;
362344µs if ( defined $body ) {
363
364 # There *is* a risk that a unicode string could reach this far - for
365 # example, if it comes from a plugin. We need to force such strings
366 # into the "Foswiki canonical" representation of a string of bytes.
367 # The output may be crap, but at least it won't trigger a
368 # "Wide character in print" error.
36914µs if ( utf8::is_utf8($body)
# spent 4µs making 1 call to utf8::is_utf8
370 and ( $Foswiki::cfg{Site}{CharSet} ne 'utf-8' ) )
371 {
372 require Encode;
373
374#used to encode to 'iso-8859-1', but that seems wrong in light of the cfg settings
375 $body = Encode::encode( $Foswiki::cfg{Site}{CharSet}, $body, 0 );
376 }
377 $this->{headers}->{'Content-Length'} = length($body);
378 $this->{body} = $body;
379 }
380 return $this->{body};
381}
382
383=begin TML
384
385---++ ObjectMethod redirect( $uri, $status, $cookies |
386 -Location => $uri,
387 -Status => $status,
388 -Cookies => $cookies )
389
390Populate object with redirect response headers.
391
392=$uri= *must* be passed. Others are optional.
393
394CGI Compatibility Note: It doesn't support -target or -nph
395
396=cut
397
398sub redirect {
399 my ( $this, @p ) = @_;
400 ASSERT( !$this->{outputHasStarted}, 'Too late to redirect' ) if DEBUG;
401 my ( $url, $status, $cookies ) = CGI::Util::rearrange(
402 [ [qw(LOCATION URL URI)], 'STATUS', [qw(COOKIE COOKIES)], ], @p );
403
404 return unless $url;
405 return if ( $status && $status !~ /^\s*3\d\d.*/ );
406
407 my @headers = ( -Location => $url );
408 push @headers, '-Status' => ( $status || 302 );
409 push @headers, '-Cookie' => $cookies if $cookies;
410 $this->header(@headers);
411}
412
413=begin TML
414
415---++ ObjectMethod print(...)
416
417Add content to the end of the body.
418
419=cut
420
421
# spent 153µs (79+74) within Foswiki::Response::print which was called: # once (79µs+74µs) by Foswiki::writeCompletePage at line 843 of /usr/local/src/github.com/foswiki/core/lib/Foswiki.pm
sub print {
422373µs my $this = shift;
423 $this->{body} = '' unless defined $this->{body};
424174µs $this->body( $this->{body} . join( '', @_ ) );
# spent 74µs making 1 call to Foswiki::Response::body
425}
426
427=begin TML
428
429---++ ObjectMethod outputHasStarted([$boolean])
430
431Get/set the output-has-started flag. This is used by the Foswiki::Engine
432to separate header and body output. Once output has started, the headers
433cannot be changed (though the body can be modified)
434
435=cut
436
437
# spent 10µs within Foswiki::Response::outputHasStarted which was called: # once (10µs+0s) by Foswiki::Engine::finalize at line 295 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Engine.pm
sub outputHasStarted {
438314µs my ( $this, $flag ) = @_;
439 $this->{outputHasStarted} = $flag if defined $flag;
440 return $this->{outputHasStarted};
441}
442
44314µs1;
444__END__
 
# spent 64µs within Foswiki::Response::CORE:subst which was called 12 times, avg 5µs/call: # 6 times (26µs+0s) by Foswiki::Response::getHeader at line 219, avg 4µs/call # 4 times (22µs+0s) by Foswiki::Response::setDefaultHeaders at line 244, avg 6µs/call # 2 times (16µs+0s) by Foswiki::Response::pushHeader at line 320, avg 8µs/call
sub Foswiki::Response::CORE:subst; # opcode
# spent 95µs within Foswiki::Response::CORE:substcont which was called 36 times, avg 3µs/call: # 18 times (43µs+0s) by Foswiki::Response::getHeader at line 219, avg 2µs/call # 12 times (33µs+0s) by Foswiki::Response::setDefaultHeaders at line 244, avg 3µs/call # 6 times (19µs+0s) by Foswiki::Response::pushHeader at line 320, avg 3µs/call
sub Foswiki::Response::CORE:substcont; # opcode