Filename | /var/www/foswikidev/core/lib/Foswiki/Engine.pm |
Statements | Executed 46 statements in 1.69ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 52µs | 315µs | prepare | Foswiki::Engine::
1 | 1 | 1 | 43µs | 236µs | __ANON__[:110] | Foswiki::Engine::
1 | 1 | 1 | 39µs | 1.18ms | finalizeBody | Foswiki::Engine::
1 | 1 | 1 | 39µs | 1.22ms | finalize | Foswiki::Engine::
1 | 1 | 1 | 13µs | 26µs | BEGIN@17 | Foswiki::Engine::
1 | 1 | 1 | 10µs | 14µs | BEGIN@18 | Foswiki::Engine::
1 | 1 | 1 | 10µs | 32µs | BEGIN@20 | Foswiki::Engine::
1 | 1 | 1 | 9µs | 9µs | new | Foswiki::Engine::
1 | 1 | 1 | 8µs | 149µs | BEGIN@19 | Foswiki::Engine::
1 | 1 | 1 | 4µs | 4µs | prepareWrite | Foswiki::Engine::
1 | 1 | 1 | 4µs | 4µs | BEGIN@21 | Foswiki::Engine::
1 | 1 | 1 | 4µs | 4µs | BEGIN@23 | Foswiki::Engine::
1 | 1 | 1 | 2µs | 2µs | prepareBody | Foswiki::Engine::
1 | 1 | 1 | 2µs | 2µs | prepareBodyParameters | Foswiki::Engine::
1 | 1 | 1 | 1µs | 1µs | finalizeUploads | Foswiki::Engine::
1 | 1 | 1 | 1µs | 1µs | prepareUploads | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | __ANON__[:125] | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | __ANON__[:155] | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | finalizeCookies | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | finalizeError | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | finalizeHeaders | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | flush | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | prepareConnection | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | prepareCookies | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | prepareHeaders | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | preparePath | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | prepareQueryParameters | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | run | Foswiki::Engine::
0 | 0 | 0 | 0s | 0s | write | Foswiki::Engine::
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::Engine | ||||
6 | |||||
7 | The engine class is a singleton that implements details about Foswiki's | ||||
8 | execution mode. This is the base class and implements basic behavior. | ||||
9 | |||||
10 | Each engine should inherits from this and overload methods necessary | ||||
11 | to achieve correct behavior. | ||||
12 | |||||
13 | =cut | ||||
14 | |||||
15 | package Foswiki::Engine; | ||||
16 | |||||
17 | 2 | 33µs | 2 | 38µs | # spent 26µs (13+12) within Foswiki::Engine::BEGIN@17 which was called:
# once (13µs+12µs) by Foswiki::Engine::CLI::BEGIN@20 at line 17 # spent 26µs making 1 call to Foswiki::Engine::BEGIN@17
# spent 12µs making 1 call to strict::import |
18 | 2 | 28µs | 2 | 19µs | # spent 14µs (10+4) within Foswiki::Engine::BEGIN@18 which was called:
# once (10µs+4µs) by Foswiki::Engine::CLI::BEGIN@20 at line 18 # spent 14µs making 1 call to Foswiki::Engine::BEGIN@18
# spent 4µs making 1 call to warnings::import |
19 | 2 | 30µs | 2 | 290µs | # spent 149µs (8+141) within Foswiki::Engine::BEGIN@19 which was called:
# once (8µs+141µs) by Foswiki::Engine::CLI::BEGIN@20 at line 19 # spent 149µs making 1 call to Foswiki::Engine::BEGIN@19
# spent 141µs making 1 call to Error::import |
20 | 2 | 25µs | 2 | 55µs | # spent 32µs (10+22) within Foswiki::Engine::BEGIN@20 which was called:
# once (10µs+22µs) by Foswiki::Engine::CLI::BEGIN@20 at line 20 # spent 32µs making 1 call to Foswiki::Engine::BEGIN@20
# spent 22µs making 1 call to Exporter::import |
21 | 2 | 47µs | 1 | 4µs | # spent 4µs within Foswiki::Engine::BEGIN@21 which was called:
# once (4µs+0s) by Foswiki::Engine::CLI::BEGIN@20 at line 21 # spent 4µs making 1 call to Foswiki::Engine::BEGIN@21 |
22 | |||||
23 | # spent 4µs within Foswiki::Engine::BEGIN@23 which was called:
# once (4µs+0s) by Foswiki::Engine::CLI::BEGIN@20 at line 28 | ||||
24 | 1 | 4µs | if ( $Foswiki::cfg{UseLocale} ) { | ||
25 | require locale; | ||||
26 | import locale(); | ||||
27 | } | ||||
28 | 1 | 1.35ms | 1 | 4µs | } # spent 4µs making 1 call to Foswiki::Engine::BEGIN@23 |
29 | |||||
30 | =begin TML | ||||
31 | |||||
32 | ---++ ClassMethod new() -> $engine | ||||
33 | |||||
34 | Constructs an engine object. | ||||
35 | |||||
36 | =cut | ||||
37 | |||||
38 | # spent 9µs within Foswiki::Engine::new which was called:
# once (9µs+0s) by Foswiki::BEGIN@176 at line 1 of (eval 100)[/var/www/foswikidev/core/lib/Foswiki.pm:632] | ||||
39 | 1 | 700ns | my $proto = shift; | ||
40 | 1 | 500ns | my $class = ref($proto) || $proto; | ||
41 | 1 | 600ns | my $this = {}; | ||
42 | 1 | 9µs | return bless $this, $class; | ||
43 | } | ||||
44 | |||||
45 | =begin TML | ||||
46 | |||||
47 | ---++ ObjectMethod run() | ||||
48 | |||||
49 | Start point to Runtime Engines. | ||||
50 | |||||
51 | =cut | ||||
52 | |||||
53 | sub run { | ||||
54 | my $this = shift; | ||||
55 | my $req = $this->prepare(); | ||||
56 | if ( ref($req) ) { | ||||
57 | my $res = Foswiki::UI::handleRequest($req); | ||||
58 | $this->finalize( $res, $req ); | ||||
59 | } | ||||
60 | } | ||||
61 | |||||
62 | =begin TML | ||||
63 | |||||
64 | ---++ ObjectMethod prepare() -> $req | ||||
65 | |||||
66 | Initialize a Foswiki::Request object by calling many preparation methods | ||||
67 | and returns it, or a status code in case of error. | ||||
68 | |||||
69 | =cut | ||||
70 | |||||
71 | # spent 315µs (52+263) within Foswiki::Engine::prepare which was called:
# once (52µs+263µs) by Foswiki::Engine::CLI::run at line 58 of /var/www/foswikidev/core/lib/Foswiki/Engine/CLI.pm | ||||
72 | 1 | 700ns | my $this = shift; | ||
73 | 1 | 300ns | my $req; | ||
74 | |||||
75 | 1 | 2µs | if ( $Foswiki::cfg{Store}{overrideUmask} && $Foswiki::cfg{OS} ne 'WINDOWS' ) | ||
76 | { | ||||
77 | |||||
78 | # Note: The addition of zero is required to force dirPermission and filePermission | ||||
79 | # to be numeric. Without the additition, certain values of the permissions cause | ||||
80 | # runtime errors about illegal characters in subtraction. "and" with 777 to prevent | ||||
81 | # sticky-bits from breaking the umask. | ||||
82 | my $oldUmask = umask( | ||||
83 | ( | ||||
84 | oct(777) - ( | ||||
85 | ( | ||||
86 | $Foswiki::cfg{Store}{dirPermission} + 0 | | ||||
87 | $Foswiki::cfg{Store}{filePermission} + 0 | ||||
88 | ) | ||||
89 | ) & oct(777) | ||||
90 | ) | ||||
91 | ); | ||||
92 | |||||
93 | #my $umask = sprintf('%04o', umask() ); | ||||
94 | #$oldUmask = sprintf('%04o', $oldUmask ); | ||||
95 | #my $dirPerm = sprintf('%04o', $Foswiki::cfg{Store}{dirPermission}+0 ); | ||||
96 | #my $filePerm = sprintf('%04o', $Foswiki::cfg{Store}{filePermission}+0 ); | ||||
97 | #print STDERR " ENGINE changes $oldUmask to $umask from $dirPerm and $filePerm \n"; | ||||
98 | } | ||||
99 | |||||
100 | # spent 236µs (43+193) within Foswiki::Engine::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Engine.pm:110] which was called:
# once (43µs+193µs) by Error::subs::try at line 419 of Error.pm | ||||
101 | 1 | 4µs | 1 | 38µs | $req = Foswiki::Request->new(); # spent 38µs making 1 call to Foswiki::Request::new |
102 | 1 | 2µs | 1 | 16µs | $this->prepareConnection($req); # spent 16µs making 1 call to Foswiki::Engine::CLI::prepareConnection |
103 | 1 | 2µs | 1 | 108µs | $this->prepareQueryParameters($req); # spent 108µs making 1 call to Foswiki::Engine::CLI::prepareQueryParameters |
104 | 1 | 3µs | 1 | 11µs | $this->prepareHeaders($req); # spent 11µs making 1 call to Foswiki::Engine::CLI::prepareHeaders |
105 | 1 | 2µs | 1 | 900ns | $this->prepareCookies($req); # spent 900ns making 1 call to Foswiki::Engine::CLI::prepareCookies |
106 | 1 | 2µs | 1 | 15µs | $this->preparePath($req); # spent 15µs making 1 call to Foswiki::Engine::CLI::preparePath |
107 | 1 | 5µs | 1 | 2µs | $this->prepareBody($req); # spent 2µs making 1 call to Foswiki::Engine::prepareBody |
108 | 1 | 4µs | 1 | 2µs | $this->prepareBodyParameters($req); # spent 2µs making 1 call to Foswiki::Engine::prepareBodyParameters |
109 | 1 | 6µs | 1 | 1µs | $this->prepareUploads($req); # spent 1µs making 1 call to Foswiki::Engine::prepareUploads |
110 | } | ||||
111 | catch Foswiki::EngineException with { | ||||
112 | my $e = shift; | ||||
113 | my $res = $e->{response}; | ||||
114 | unless ( defined $res ) { | ||||
115 | $res = new Foswiki::Response(); | ||||
116 | $res->header( -type => 'text/html', -status => $e->{status} ); | ||||
117 | my $html = CGI::start_html( $e->{status} . ' Bad Request' ); | ||||
118 | $html .= CGI::h1( {}, 'Bad Request' ); | ||||
119 | $html .= CGI::p( {}, $e->{reason} ); | ||||
120 | $html .= CGI::end_html(); | ||||
121 | $res->print($html); | ||||
122 | } | ||||
123 | $this->finalizeError( $res, $req ); | ||||
124 | return $e->{status}; | ||||
125 | } | ||||
126 | otherwise { | ||||
127 | my $e = shift; | ||||
128 | my $res = Foswiki::Response->new(); | ||||
129 | my $mess = | ||||
130 | $e->can('stringify') | ||||
131 | ? $e->stringify() | ||||
132 | : 'Unknown ' . ref($e) . ' exception: ' . $@; | ||||
133 | $res->header( -type => 'text/plain', -status => '500' ); | ||||
134 | if (DEBUG) { | ||||
135 | |||||
136 | # output the full message and stacktrace to the browser | ||||
137 | $res->print($mess); | ||||
138 | } | ||||
139 | else { | ||||
140 | print STDERR $mess; | ||||
141 | |||||
142 | # tell the browser where to look for more help | ||||
143 | my $text = | ||||
144 | 'Foswiki detected an internal error - please check your Foswiki logs and webserver logs for more information.' | ||||
145 | . "\n\n"; | ||||
146 | $mess =~ s/ at .*$//s; | ||||
147 | |||||
148 | # cut out pathnames from public announcement | ||||
149 | $mess =~ s#/[\w./]+#path#g; | ||||
150 | $text .= $mess; | ||||
151 | $res->print($text); | ||||
152 | } | ||||
153 | $this->finalizeError( $res, $req ); | ||||
154 | return 500; # Internal server error | ||||
155 | 1 | 42µs | 4 | 263µs | }; # spent 252µs making 1 call to Error::subs::try
# spent 5µs making 1 call to Error::subs::otherwise
# spent 4µs making 1 call to Error::catch
# spent 2µs making 1 call to Error::subs::with |
156 | 1 | 3µs | return $req; | ||
157 | } | ||||
158 | |||||
159 | =begin TML | ||||
160 | |||||
161 | ---++ ObjectMethod prepareConnection( $req ) | ||||
162 | |||||
163 | Abstract method, must be defined by inherited classes. | ||||
164 | * =$req= - Foswiki::Request object to populate | ||||
165 | |||||
166 | Should fill remoteAddr, method and secure fields of =$req= object. | ||||
167 | |||||
168 | =cut | ||||
169 | |||||
170 | sub prepareConnection { } | ||||
171 | |||||
172 | =begin TML | ||||
173 | |||||
174 | ---++ ObjectMethod prepareQueryParameters( $req, $queryString ) | ||||
175 | |||||
176 | Populates $req with parameters extracted by parsing a | ||||
177 | byte string (which may include url-encoded characters, which may | ||||
178 | in turn be parts of utf8-encoded characters). | ||||
179 | |||||
180 | Note that parameter names and values are decoded to unicode. | ||||
181 | |||||
182 | =cut | ||||
183 | |||||
184 | sub prepareQueryParameters { | ||||
185 | my ( $this, $req, $queryString ) = @_; | ||||
186 | my @pairs = split /[&;]/, $queryString; | ||||
187 | my ( $param, $value, %params, @plist ); | ||||
188 | foreach my $pair (@pairs) { | ||||
189 | ( $param, $value ) = split( '=', $pair, 2 ); | ||||
190 | |||||
191 | # url decode | ||||
192 | if ( defined $value ) { | ||||
193 | $value =~ tr/+/ /; | ||||
194 | $value =~ s/%([0-9A-F]{2})/chr(hex($1))/gei; | ||||
195 | $value = Foswiki::decode_utf8($value); | ||||
196 | } | ||||
197 | if ( defined $param ) { | ||||
198 | $param =~ tr/+/ /; | ||||
199 | $param =~ s/%([0-9A-F]{2})/chr(hex($1))/gei; | ||||
200 | $param = Foswiki::decode_utf8($param); | ||||
201 | push( @{ $params{$param} }, $value ); | ||||
202 | push( @plist, $param ); | ||||
203 | } | ||||
204 | } | ||||
205 | foreach my $param (@plist) { | ||||
206 | (undef) = $req->queryParam( $param, $params{$param} ); | ||||
207 | } | ||||
208 | } | ||||
209 | |||||
210 | =begin TML | ||||
211 | |||||
212 | ---++ ObjectMethod prepareHeaders( $req ) | ||||
213 | |||||
214 | Abstract method, must be defined by inherited classes. | ||||
215 | * =$req= - Foswiki::Request object to populate | ||||
216 | |||||
217 | Should fill $req's headers and remoteUser fields. | ||||
218 | |||||
219 | =cut | ||||
220 | |||||
221 | sub prepareHeaders { } | ||||
222 | |||||
223 | =begin TML | ||||
224 | |||||
225 | ---++ ObjectMethod preparePath( $req ) | ||||
226 | |||||
227 | Abstract method, must be defined by inherited classes. | ||||
228 | * =$req= - Foswiki::Request object to populate | ||||
229 | |||||
230 | Should fill $req's uri and pathInfo fields. | ||||
231 | |||||
232 | =cut | ||||
233 | |||||
234 | sub preparePath { } | ||||
235 | |||||
236 | =begin TML | ||||
237 | |||||
238 | ---++ ObjectMethod prepareCookies( $req ) | ||||
239 | |||||
240 | * =$req= - Foswiki::Request object to populate | ||||
241 | |||||
242 | Should fill $req's cookie field. This method take cookie data from | ||||
243 | previously populated headers field and initializes from it. Maybe | ||||
244 | doesn't need to overload in children classes. | ||||
245 | |||||
246 | =cut | ||||
247 | |||||
248 | sub prepareCookies { | ||||
249 | my ( $this, $req ) = @_; | ||||
250 | eval { require CGI::Cookie }; | ||||
251 | throw Error::Simple($@) if $@; | ||||
252 | $req->cookies( scalar( CGI::Cookie->parse( $req->header('Cookie') ) ) ) | ||||
253 | if $req->header('Cookie'); | ||||
254 | } | ||||
255 | |||||
256 | =begin TML | ||||
257 | |||||
258 | ---++ ObjectMethod prepareBody( $req ) | ||||
259 | |||||
260 | Abstract method, must be defined by inherited classes. | ||||
261 | * =$req= - Foswiki::Request object to populate | ||||
262 | |||||
263 | Should perform any initialization tasks related to body processing. | ||||
264 | |||||
265 | =cut | ||||
266 | |||||
267 | 1 | 3µs | # spent 2µs within Foswiki::Engine::prepareBody which was called:
# once (2µs+0s) by Foswiki::Engine::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Engine.pm:110] at line 107 | ||
268 | |||||
269 | =begin TML | ||||
270 | |||||
271 | ---++ ObjectMethod prepareBodyParameters( $req ) | ||||
272 | |||||
273 | Abstract method, must be defined by inherited classes. | ||||
274 | * =$req= - Foswiki::Request object to populate | ||||
275 | |||||
276 | Should fill $req's body parameters (parameters that are set in the | ||||
277 | request body, as against the query string). Implementations must | ||||
278 | convert parameter values to unicode. | ||||
279 | |||||
280 | =cut | ||||
281 | |||||
282 | 1 | 3µs | # spent 2µs within Foswiki::Engine::prepareBodyParameters which was called:
# once (2µs+0s) by Foswiki::Engine::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Engine.pm:110] at line 108 | ||
283 | |||||
284 | =begin TML | ||||
285 | |||||
286 | ---++ ObjectMethod prepareUploads( $req ) | ||||
287 | |||||
288 | Abstract method, must be defined by inherited classes. | ||||
289 | * =$req= - Foswiki::Request object to populate | ||||
290 | |||||
291 | Should fill $req's {uploads} field. This is a hashref whose keys are | ||||
292 | upload names and values Foswiki::Request::Upload objects. | ||||
293 | |||||
294 | Implementations must convert upload names to unicode. | ||||
295 | |||||
296 | =cut | ||||
297 | |||||
298 | 1 | 3µs | # spent 1µs within Foswiki::Engine::prepareUploads which was called:
# once (1µs+0s) by Foswiki::Engine::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Engine.pm:110] at line 109 | ||
299 | |||||
300 | =begin TML | ||||
301 | |||||
302 | ---++ ObjectMethod finalize($res, $req) | ||||
303 | |||||
304 | Finalizes the request by calling many methods to send response to client and | ||||
305 | take any appropriate finalize actions, such as delete temporary files. | ||||
306 | * =$res= is the Foswiki::Response object | ||||
307 | * =$req= it the Foswiki::Request object. | ||||
308 | |||||
309 | =cut | ||||
310 | |||||
311 | # spent 1.22ms (39µs+1.19) within Foswiki::Engine::finalize which was called:
# once (39µs+1.19ms) by Foswiki::Engine::CLI::run at line 61 of /var/www/foswikidev/core/lib/Foswiki/Engine/CLI.pm | ||||
312 | 1 | 2µs | my ( $this, $res, $req ) = @_; | ||
313 | 1 | 8µs | 1 | 4µs | if ( $res->outputHasStarted() ) { # spent 4µs making 1 call to Foswiki::Response::outputHasStarted |
314 | $this->flush( $res, $req ); | ||||
315 | } | ||||
316 | else { | ||||
317 | 1 | 8µs | 1 | 1µs | $this->finalizeUploads( $res, $req ); # spent 1µs making 1 call to Foswiki::Engine::finalizeUploads |
318 | 1 | 3µs | 1 | 2µs | $this->finalizeHeaders( $res, $req ); # spent 2µs making 1 call to Foswiki::Engine::CLI::finalizeHeaders |
319 | 1 | 7µs | 1 | 1.18ms | $this->finalizeBody($res); # spent 1.18ms making 1 call to Foswiki::Engine::finalizeBody |
320 | } | ||||
321 | } | ||||
322 | |||||
323 | =begin TML | ||||
324 | |||||
325 | ---++ ObjectMethod finalizeUploads( $res, $req ) | ||||
326 | |||||
327 | Abstract method, must be defined by inherited classes. | ||||
328 | * =$res= - Foswiki::Response object to get data from | ||||
329 | * =$req= - Foswiki::Request object to get data from | ||||
330 | |||||
331 | Should delete any temp files created in preparation phase. | ||||
332 | |||||
333 | =cut | ||||
334 | |||||
335 | 1 | 5µs | # spent 1µs within Foswiki::Engine::finalizeUploads which was called:
# once (1µs+0s) by Foswiki::Engine::finalize at line 317 | ||
336 | |||||
337 | =begin TML | ||||
338 | |||||
339 | ---++ ObjectMethod finalizeError( $res, $req ) | ||||
340 | |||||
341 | Called if some engine especific error happens. | ||||
342 | |||||
343 | * =$res= - Foswiki::Response object to get data from | ||||
344 | * =$req= - Foswiki::Request object to get data from | ||||
345 | |||||
346 | =cut | ||||
347 | |||||
348 | sub finalizeError { | ||||
349 | my ( $this, $res, $req ) = @_; | ||||
350 | $this->finalizeHeaders( $res, $req ); | ||||
351 | $this->finalizeBody( $res, $req ); | ||||
352 | |||||
353 | # Item12590: prevent duplicated output by later call to finalize() | ||||
354 | $res->body(''); | ||||
355 | $res->outputHasStarted(1); | ||||
356 | } | ||||
357 | |||||
358 | =begin TML | ||||
359 | |||||
360 | ---++ ObjectMethod finalizeHeaders( $res, $req ) | ||||
361 | |||||
362 | Base method, must be redefined by inherited classes. For convenience | ||||
363 | this method deals with HEAD requests related stuff. Children classes | ||||
364 | should call SUPER. | ||||
365 | * =$res= - Foswiki::Response object to get data from | ||||
366 | * =$req= - Foswiki::Request object to get data from | ||||
367 | |||||
368 | Should call finalizeCookies and then send $res' headers to client. | ||||
369 | |||||
370 | =cut | ||||
371 | |||||
372 | sub finalizeHeaders { | ||||
373 | my ( $this, $res, $req ) = @_; | ||||
374 | $this->finalizeCookies($res); | ||||
375 | if ( $req && $req->method() && uc( $req->method() ) eq 'HEAD' ) { | ||||
376 | $res->body(''); | ||||
377 | $res->deleteHeader('Content-Length'); | ||||
378 | } | ||||
379 | } | ||||
380 | |||||
381 | =begin TML | ||||
382 | |||||
383 | ---++ ObjectMethod finalizeCookies( $res ) | ||||
384 | |||||
385 | * =$res= - Foswiki::Response object to both get data from and populate | ||||
386 | |||||
387 | Should populate $res' headers field with cookies, if any. | ||||
388 | |||||
389 | =cut | ||||
390 | |||||
391 | sub finalizeCookies { | ||||
392 | my ( $this, $res ) = @_; | ||||
393 | |||||
394 | # SMELL: Review comment below, from CGI: | ||||
395 | # if the user indicates an expiration time, then we need | ||||
396 | # both an Expires and a Date header (so that the browser is | ||||
397 | # uses OUR clock) | ||||
398 | $res->pushHeader( 'Set-Cookie', | ||||
399 | Scalar::Util::blessed $_ | ||||
400 | && $_->isa('CGI::Cookie') ? $_->as_string : $_ ) | ||||
401 | foreach $res->cookies; | ||||
402 | } | ||||
403 | |||||
404 | =begin TML | ||||
405 | |||||
406 | ---++ ObjectMethod finalizeBody( $res, $req ) | ||||
407 | |||||
408 | * =$res= - Foswiki::Response object to get data from | ||||
409 | * =$req= - Foswiki::Request object to get data from | ||||
410 | |||||
411 | Should send $res' body to client. This method calls =write()= | ||||
412 | as needed, so engines should redefine that method insted of this one. | ||||
413 | |||||
414 | =cut | ||||
415 | |||||
416 | # spent 1.18ms (39µs+1.14) within Foswiki::Engine::finalizeBody which was called:
# once (39µs+1.14ms) by Foswiki::Engine::finalize at line 319 | ||||
417 | 1 | 1µs | my ( $this, $res, $req ) = @_; | ||
418 | 1 | 4µs | 1 | 1.05ms | my $body = $res->body; # spent 1.05ms making 1 call to Foswiki::Response::body |
419 | 1 | 400ns | return unless defined $body; | ||
420 | 1 | 10µs | 1 | 4µs | $this->prepareWrite($res); # spent 4µs making 1 call to Foswiki::Engine::prepareWrite |
421 | 1 | 19µs | 1 | 6µs | if ( Scalar::Util::blessed($body) && $body->can('read') # spent 6µs making 1 call to Scalar::Util::blessed |
422 | or ref $body eq 'GLOB' ) | ||||
423 | { | ||||
424 | while ( !eof $body ) { | ||||
425 | read $body, my $buffer, 4096; | ||||
426 | last unless $this->write($buffer); | ||||
427 | } | ||||
428 | close $body; | ||||
429 | } | ||||
430 | else { | ||||
431 | 1 | 3µs | 1 | 77µs | $this->write($body); # spent 77µs making 1 call to Foswiki::Engine::CLI::write |
432 | } | ||||
433 | } | ||||
434 | |||||
435 | =begin TML | ||||
436 | |||||
437 | ---++ flush($res, $req) | ||||
438 | |||||
439 | Forces the response headers to be emitted if they haven't already been sent | ||||
440 | (note that this may in some circumstances result in cookies being missed) | ||||
441 | before flushing what is in the body so far. | ||||
442 | |||||
443 | Before headers are sent, any Content-length is removed, as a call to | ||||
444 | flush is a statement that there's more to follow, but we don't know | ||||
445 | how much at this point. | ||||
446 | |||||
447 | This function should be used with great care! It requires that the output | ||||
448 | headers are fully complete before it is first called. Once it *has* been | ||||
449 | called, the response object will refuse any modifications that would alter | ||||
450 | the header. | ||||
451 | |||||
452 | =cut | ||||
453 | |||||
454 | sub flush { | ||||
455 | my ( $this, $res, $req ) = @_; | ||||
456 | |||||
457 | unless ( $res->outputHasStarted() ) { | ||||
458 | $res->deleteHeader('Content-Length'); | ||||
459 | $this->finalizeUploads( $res, $req ); | ||||
460 | $this->finalizeHeaders( $res, $req ); | ||||
461 | $this->prepareWrite($res); | ||||
462 | $res->outputHasStarted(1); | ||||
463 | } | ||||
464 | |||||
465 | my $body = $res->body(); | ||||
466 | |||||
467 | if ( Scalar::Util::blessed($body) || ref($body) eq 'GLOB' ) { | ||||
468 | throw Foswiki::EngineException('Cannot flush non-text response body'); | ||||
469 | } | ||||
470 | |||||
471 | $this->write($body); | ||||
472 | $res->body(''); | ||||
473 | } | ||||
474 | |||||
475 | =begin TML | ||||
476 | |||||
477 | ---++ ObjectMethod prepareWrite( $res ) | ||||
478 | |||||
479 | Abstract method, may be defined by inherited classes. | ||||
480 | * =$res= - Foswiki::Response object to get data from | ||||
481 | |||||
482 | Should perform any task needed before writing. | ||||
483 | That's ok if none needed ;-) | ||||
484 | |||||
485 | =cut | ||||
486 | |||||
487 | 1 | 4µs | # spent 4µs within Foswiki::Engine::prepareWrite which was called:
# once (4µs+0s) by Foswiki::Engine::finalizeBody at line 420 | ||
488 | |||||
489 | =begin TML | ||||
490 | |||||
491 | ---++ ObjectMethod write( $buffer ) | ||||
492 | |||||
493 | Abstract method, must be defined by inherited classes. | ||||
494 | * =$buffer= - chunk of data to be sent | ||||
495 | |||||
496 | Should send $buffer to client. | ||||
497 | |||||
498 | =cut | ||||
499 | |||||
500 | sub write { | ||||
501 | ASSERT('Pure virtual method - should never be called'); | ||||
502 | } | ||||
503 | |||||
504 | 1 | 2µs | 1; | ||
505 | __END__ |