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