File Coverage

blib/lib/Apache2/ASP/HTTPContext.pm
Criterion Covered Total %
statement 39 235 16.6
branch 0 72 0.0
condition 0 6 0.0
subroutine 13 54 24.0
pod 8 34 23.5
total 60 401 14.9


line stmt bran cond sub pod time code
1              
2             package Apache2::ASP::HTTPContext;
3              
4 23     23   102 use strict;
  23         29  
  23         729  
5 23     23   173 use warnings 'all';
  23         28  
  23         987  
6 23     23   1861 use Apache2::ASP::ConfigLoader;
  23         32  
  23         520  
7 23     23   8894 use Apache2::ASP::Response;
  23         44  
  23         695  
8 23     23   8435 use Apache2::ASP::Request;
  23         40  
  23         913  
9 23     23   8118 use Apache2::ASP::Server;
  23         62  
  23         953  
10 23     23   116 use Carp qw( cluck confess );
  23         34  
  23         1535  
11 23     23   99 use Scalar::Util 'weaken';
  23         33  
  23         959  
12 23     23   98 use HTTP::Headers;
  23         35  
  23         477  
13              
14 23     23   10044 use Apache2::ASP::SessionStateManager::NonPersisted;
  23         60  
  23         884  
15 23     23   11455 use Apache2::ASP::ApplicationStateManager::NonPersisted;
  23         44  
  23         6768  
16              
17             our $instance;
18             our $ClassName = __PACKAGE__;
19             our %StartedServers = ( );
20              
21             #==============================================================================
22             sub current
23             {
24 0     0 1   my $class = shift;
25            
26 0           return $instance;
27             }# end current()
28              
29              
30             #==============================================================================
31             sub new
32             {
33 0     0 0   my ($class, %args) = @_;
34            
35 0           my $s = bless {
36             config => Apache2::ASP::ConfigLoader->load(),
37             }, $class;
38 0           $s->config->_init_inc();
39            
40 0           return $instance = $s;
41             }# end new()
42              
43              
44             #==============================================================================
45             sub setup_request
46             {
47 0     0 0   my ($s, $requestrec, $cgi) = @_;
48            
49 0           $s->{_is_setup}++;
50            
51 0           $s->{r} = $requestrec;
52 0           $s->{cgi} = $cgi;
53              
54 0           $s->_setup_headers_out();
55 0           $s->_setup_headers_in();
56            
57 0           $s->{connection} = $s->r->connection;
58            
59 0           $s->{response} = Apache2::ASP::Response->new();
60 0           $s->{request} = Apache2::ASP::Request->new();
61 0           $s->{server} = Apache2::ASP::Server->new();
62              
63 0           my $conns = $s->config->data_connections;
64 0 0         if( $s->do_disable_application_state )
65             {
66 0           $s->{application} = Apache2::ASP::ApplicationStateManager::NonPersisted->new();
67             }
68             else
69             {
70 0           my $app_manager = $conns->application->manager;
71 0           $s->_load_class( $app_manager );
72 0           $s->{application} = $app_manager->new();
73             }# end if()
74            
75 0 0         if( $s->do_disable_session_state )
76             {
77 0           $s->{session} = Apache2::ASP::SessionStateManager::NonPersisted->new();
78             }
79             else
80             {
81 0           my $session_manager = $conns->session->manager;
82 0           $s->_load_class( $session_manager );
83 0           $s->{session} = $session_manager->new();
84             }# end if()
85            
86             # Make the global Stash object:
87 0           $s->{stash} = { };
88            
89 0           $s->{global_asa} = $s->resolve_global_asa_class( );
90             {
91 23     23   122 no warnings 'uninitialized';
  23         34  
  23         25297  
  0            
92             $s->{global_asa}->init_asp_objects( $s )
93 0 0         unless $s->r->headers_in->{'content-type'} =~ m/multipart/;
94             }
95            
96 0           $s->_load_class( $s->config->web->handler_resolver );
97 0           eval {
98 0           $s->{handler} = $s->config->web->handler_resolver->new()->resolve_request_handler( $s->r->uri );
99             };
100 0 0         if( $@ )
101             {
102 0           $s->server->{LastError} = $@;
103 0           return $s->handle_error;
104             }# end if()
105            
106 0           return 1;
107             }# end setup_request()
108              
109              
110             #==============================================================================
111             sub _setup_headers_out
112             {
113 0     0     my ($s) = @_;
114            
115 0           $s->{headers_out} = HTTP::Headers->new();
116             }# end _setup_headers_out()
117              
118              
119             #==============================================================================
120             sub _setup_headers_in
121             {
122 0     0     my ($s) = @_;
123            
124 0           my $h = $s->r->headers_in;
125 0 0         if( UNIVERSAL::isa($h, 'HTTP::Headers') )
126             {
127 0           $s->{headers_in} = $h;
128             }
129             else
130             {
131 0           my $headers_in = HTTP::Headers->new();
132 0           while( my ($k,$v) = each(%$h) )
133             {
134 0           $headers_in->push_header( $k => $v );
135             }# end while()
136 0           $s->{headers_in} = $headers_in;
137             }# end if()
138             }# end _setup_headers_in()
139              
140              
141             #==============================================================================
142             sub do_disable_session_state
143             {
144 0     0 0   my ($s) = @_;
145            
146 0           my ($uri) = split /\?/, $s->r->uri;
147 0           my ($yes) = grep { $_->disable_session } grep {
148 0 0         if( my $pattern = $_->uri_match )
  0            
149             {
150 0           $uri =~ m/$pattern/
151             }
152             else
153             {
154 0           $uri eq $_->uri_equals;
155             }# end if()
156             } $s->config->web->disable_persistence;
157            
158 0           return $yes;
159             }# end do_disable_session_state()
160              
161              
162             #==============================================================================
163             sub do_disable_application_state
164             {
165 0     0 0   my ($s) = @_;
166            
167 0           my ($uri) = split /\?/, $s->r->uri;
168 0           my ($yes) = grep { $_->disable_application } grep {
169 0 0         if( my $pattern = $_->uri_match )
  0            
170             {
171 0           $uri =~ m/$pattern/
172             }
173             else
174             {
175 0           $uri eq $_->uri_equals;
176             }# end if()
177             } $s->config->web->disable_persistence;
178            
179 0           return $yes;
180             }# end do_disable_application_state()
181              
182              
183             #==============================================================================
184             sub execute
185             {
186 0     0 0   my ($s, $args) = @_;
187              
188             # local $SIG{__DIE__} = \&Carp::confess;
189            
190 0 0         if( defined(my $preinit_res = $s->do_preinit) )
191             {
192 0           return $preinit_res;
193             }# end if()
194            
195             # Set up and execute any matching request filters:
196 0           my $resolver = $s->config->web->filter_resolver;
197 0           $s->_load_class( $resolver );
198 0           foreach my $filter ( $resolver->new()->resolve_request_filters( $s->r->uri ) )
199             {
200 0           $s->_load_class( $filter->class );
201 0           $filter->class->init_asp_objects( $s );
202 0     0     my $res = $s->handle_phase(sub{ $filter->class->new()->run( $s ) });
  0            
203 0 0 0       if( defined($res) && $res != -1 )
204             {
205 0           return $res;
206             }# end if()
207             }# end foreach()
208            
209 0           my $start_res = $s->handle_phase( $s->global_asa->can('Script_OnStart') );
210 0 0         return $start_res if defined( $start_res );
211            
212 0           $s->_load_class( $s->config->web->handler_runner );
213 0           eval {
214 0           $s->_load_class( $s->handler );
215 0           $s->config->web->handler_runner->new()->run_handler( $s->handler, $args );
216             };
217 0 0         if( $@ )
218             {
219 0           $s->server->{LastError} = $@;
220 0           return $s->handle_error;
221             }# end if()
222            
223 0           $s->response->Flush;
224 0           my $res = $s->end_request();
225             # if( $s->page && $s->page->directives->{OutputCache} && defined($s->{_cache_buffer}) )
226             # {
227             # if( $res == 200 || $res == 0 )
228             # {
229             # $s->page->_write_cache( \$s->{_cache_buffer} );
230             # }# end if()
231             # }# end if()
232            
233 0 0         $res = 0 if $res =~ m/^200/;
234 0           return $res;
235             }# end execute()
236              
237              
238             #==============================================================================
239             #sub _setup_inc
240             #{
241             # my $s = shift;
242             #
243             # my $www_root = $s->config->web->www_root;
244             # push @INC, $www_root unless grep { $_ eq $www_root } @INC;
245             # my %libs = map { $_ => 1 } @INC;
246             # push @INC, grep { ! $libs{$_} } $s->config->system->libs;
247             #}# end _setup_inc()
248              
249              
250             #==============================================================================
251             sub do_preinit
252             {
253 0     0 0   my $s = shift;
254            
255 0 0         unless( $s->_is_setup )
256             {
257 0           $s->setup_request( $Apache2::ASP::ModPerl::R, $Apache2::ASP::ModPerl::CGI );
258             }# end unless()
259            
260             # Initialize the Server, Application and Session:
261 0 0         unless( $StartedServers{ $s->config->web->application_name } )
262             {
263 0           my $res = $s->handle_phase(
264             $s->global_asa->can('Server_OnStart')
265             );
266 0 0         $StartedServers{ $s->config->web->application_name }++
267             unless $@;
268 0 0         return $s->end_request if $s->{did_end};
269             }# end unless()
270            
271 0 0         unless( $s->application->{__Application_Started} )
272             {
273 0           my $res = $s->handle_phase(
274             $s->global_asa->can('Application_OnStart')
275             );
276 0 0         $s->application->{__Application_Started}++ unless $@;
277 0 0         return $s->end_request if $s->{did_end};
278             }# end unless()
279            
280 0 0         unless( $s->session->{__Started} )
281             {
282 0           my $res = $s->handle_phase(
283             $s->global_asa->can('Session_OnStart')
284             );
285 0 0         $s->session->{__Started}++ unless $@;
286 0 0         return $s->end_request if $s->{did_end};
287             }# end unless()
288            
289 0           return;
290             }# end do_preinit()
291              
292              
293             #==============================================================================
294             sub handle_phase
295             {
296 0     0 0   my ($s, $ref) = @_;
297            
298 0           eval { $ref->( ) };
  0            
299 0 0         if( $@ )
300             {
301 0           $s->handle_error;
302             }# end if()
303            
304             # Undef on success:
305 0 0         return $s->response->Status =~ m/^200/ ? undef : $s->response->Status;
306             }# end handle_phase()
307              
308              
309             #==============================================================================
310             sub handle_error
311             {
312 0     0 0   my $s = shift;
313            
314 0           my $error = "$@";
315 0           $s->response->Status( 500 );
316 23     23   135 no strict 'refs';
  23         37  
  23         28568  
317              
318 0           $s->response->Clear;
319 0           my ($main, $title, $file, $line) = $error =~ m/^((.*?)\s(?:at|in)\s(.*?)\sline\s(\d+))/;
320             $s->stash->{error} = {
321 0           title => $title,
322             file => $file,
323             line => $line,
324             stacktrace => $error,
325             };
326 0           warn "[Error: @{[ HTTP::Date::time2iso() ]}] $main\n";
  0            
327            
328 0           $s->_load_class( $s->config->errors->error_handler );
329 0           my $error_handler = $s->config->errors->error_handler->new();
330 0           $error_handler->init_asp_objects( $s );
331 0           eval { $error_handler->run( $s ) };
  0            
332 0 0         confess $@ if $@;
333            
334 0           return $s->end_request;
335             }# end handle_error()
336              
337              
338             #==============================================================================
339             sub end_request
340             {
341 0     0 0   my $s = shift;
342            
343 0 0         $s->handle_phase( $s->global_asa->can('Script_OnEnd') )
344             unless $s->server->GetLastError;
345            
346 0           $s->response->End;
347 0           $s->session->save;
348 0           $s->application->save;
349 0 0         my $res = $s->response->Status =~ m/^200/ ? 0 : $s->response->Status;
350            
351 0           return $res;
352             }# end end_request()
353              
354              
355             #==============================================================================
356             sub clone
357             {
358 0     0 0   my $s = shift;
359            
360 0           return bless {%$s}, ref($s);
361             }# end clone()
362              
363              
364             #==============================================================================
365             sub get_prop
366             {
367 0     0 0   my ($s, $prop) = @_;
368            
369 0 0         $s->{parent} ? $s->{parent}->get_prop($prop) : $s->{$prop};
370             }# end get_prop()
371              
372              
373             #==============================================================================
374             sub set_prop
375             {
376 0     0 0   my ($s) = shift;
377 0           my $prop = shift;
378            
379 0 0         $s->{parent} ? $s->{parent}->set_prop($prop, @_) : $s->{$prop} = shift;
380             }# end set_prop()
381              
382 0     0 1   sub config { $_[0]->get_prop('config') }
383 0     0 1   sub session { $_[0]->get_prop('session') }
384 0     0 1   sub server { $_[0]->get_prop('server') }
385 0     0 1   sub request { $_[0]->get_prop('request') }
386 0     0 1   sub response { $_[0]->get_prop('response') }
387 0     0 1   sub application { $_[0]->get_prop('application') }
388 0     0 0   sub stash { $_[0]->get_prop('stash') }
389 0     0 0   sub global_asa { $_[0]->get_prop('global_asa') }
390 0     0     sub _is_setup { $_[0]->get_prop('_is_setup') }
391              
392 0     0 1   sub r { $_[0]->{r} }
393             sub cgi
394             {
395 0     0 0   my $s = shift;
396 0   0       $s->{cgi} ||= Apache2::ASP::SimpleCGI->new(
397             querystring => $s->r->args
398             );
399 0           return $s->{cgi};
400             }
401 0     0 0   sub handler { $_[0]->{handler} }
402 0     0 0   sub connection { $_[0]->{connection} }
403 0     0 0   sub page { $_[0]->{page} }
404              
405 0     0 0   sub headers_in { shift->get_prop('headers_in') }
406             sub send_headers
407             {
408 0     0 0   my $s = shift;
409 0 0         return if $s->{_did_send_headers};
410            
411 0           my $headers = $s->get_prop('headers_out');
412 0           my $r = $s->get_prop('r');
413 0           while( my ($k,$v) = each(%$headers) )
414             {
415 0           $r->err_headers_out->{$k} = $v;
416             }# end while()
417            
418 0           $r->rflush();
419 0           $s->{_did_send_headers}++;
420             }# end send_headers()
421              
422 0     0 0   sub headers_out { shift->get_prop('headers_out') }
423 0     0 0   sub content_type { shift->get_prop('r')->content_type( @_ ) }
424              
425              
426             sub print
427             {
428 0     0 0   my ($s, $str) = @_;
429            
430 0 0         return unless defined($str);
431 0           $s->{r}->print( $str );
432             }# end print()
433              
434              
435              
436             #==============================================================================
437             sub rflush
438             {
439 0     0 0   my $s = shift;
440            
441 0 0         $s->send_headers
442             unless $s->did_send_headers;
443            
444 0           $s->{r}->rflush();
445             }# end rflush()
446              
447 0     0 0   sub did_send_headers { shift->get_prop('_did_send_headers') }
448              
449              
450             #==============================================================================
451             sub resolve_global_asa_class
452             {
453 0     0 0   my $s = shift;
454            
455 0           my $file = $s->config->web->www_root . '/GlobalASA.pm';
456 0           my $class;
457 0 0         if( -f $file )
458             {
459 0           $class = $s->config->web->application_name . '::GlobalASA';
460 0           eval { require $file };
  0            
461 0 0         confess $@ if $@;
462             }
463             else
464             {
465 0           $class = 'Apache2::ASP::GlobalASA';
466 0           $s->_load_class( $class );
467             }# end if()
468            
469 0           return $class;
470             }# end resolve_global_asa_class()
471              
472              
473             #==============================================================================
474             sub _load_class
475             {
476 0     0     my ($s, $class) = @_;
477            
478 0           (my $file = "$class.pm") =~ s/::/\//g;
479 0 0         eval { require $file; 1 }
  0            
  0            
480             or confess "Cannot load $class: $@";
481             }# end _load_class()
482              
483              
484             #==============================================================================
485             sub AUTOLOAD
486             {
487 0     0     my $s = shift;
488            
489 0           our $AUTOLOAD;
490 0           my ($key) = $AUTOLOAD =~ m/([^:]+)$/;
491 0 0         @_ ? $s->set_prop( $key, shift ) : $s->get_prop( $key );
492             }# end AUTOLOAD()
493              
494              
495             #==============================================================================
496             sub DESTROY
497             {
498 0     0     my $s = shift;
499            
500 0           undef(%$s);
501             }# end DESTROY()
502              
503             1;# return true:
504              
505              
506             =pod
507              
508             =head1 NAME
509              
510             Apache2::ASP::HTTPContext - Contextual execution harness for ASP scripts.
511              
512             =head1 SYNOPSIS
513              
514             # Get the original mod_perl '$r' object:
515             my Apache2::RequestRec $r = $context->r;
516            
517             # Get the other traditional ASP objects:
518             my $Config = $context->config;
519             my $Request = $context->request;
520             my $Response = $context->response;
521             my $Server = $context->server;
522             my $Session = $context->session;
523             my $Application = $context->application;
524            
525             # Get the current context object from anywhere within your application:
526             my $context = Apache2::ASP::HTTPContext->current;
527              
528             =head1 DESCRIPTION
529              
530             =head1 STATIC PROPERTIES
531              
532             =head2 current
533              
534             Returns the "current" HTTPContext instance.
535              
536             =head1 PUBLIC PROPERTIES
537              
538             =head2 r
539              
540             Returns the current Apache2::RequestRec object.
541              
542             B: while in "API" or "Testing" mode, C returns the current
543             L object.
544              
545             =head2 config
546              
547             Returns the current L object.
548              
549             =head2 request
550              
551             Returns the current L object.
552              
553             =head2 response
554              
555             Returns the current L object.
556              
557             =head2 server
558              
559             Returns the current L object.
560              
561             =head2 session
562              
563             Returns the current L object.
564              
565             =head2 application
566              
567             Returns the current L object.
568            
569             =head1 BUGS
570            
571             It's possible that some bugs have found their way into this release.
572            
573             Use RT L to submit bug reports.
574            
575             =head1 HOMEPAGE
576            
577             Please visit the Apache2::ASP homepage at L to see examples
578             of Apache2::ASP in action.
579              
580             =head1 AUTHOR
581              
582             John Drago
583              
584             =head1 COPYRIGHT
585              
586             Copyright 2008 John Drago. All rights reserved.
587              
588             =head1 LICENSE
589              
590             This software is Free software and is licensed under the same terms as perl itself.
591              
592             =cut
593