File Coverage

lib/Drogo/Guts.pm
Criterion Covered Total %
statement 219 391 56.0
branch 19 112 16.9
condition 22 77 28.5
subroutine 59 95 62.1
pod 31 42 73.8
total 350 717 48.8


line stmt bran cond sub pod time code
1             package Drogo::Guts;
2 1     1   6 use strict;
  1         2  
  1         39  
3              
4 1     1   4 use Exporter;
  1         2  
  1         114  
5             our @ISA = qw(Exporter);
6              
7 1     1   8 use constant OK => 0;
  1         2  
  1         116  
8 1     1   6 use constant DECLINED => -5;
  1         2  
  1         52  
9              
10 1     1   5 use constant HTTP_OK => 200;
  1         2  
  1         63  
11 1     1   5 use constant HTTP_CREATED => 201;
  1         2  
  1         61  
12 1     1   5 use constant HTTP_ACCEPTED => 202;
  1         2  
  1         76  
13 1     1   6 use constant HTTP_NO_CONTENT => 204;
  1         2  
  1         64  
14 1     1   6 use constant HTTP_PARTIAL_CONTENT => 206;
  1         2  
  1         43  
15              
16 1     1   5 use constant HTTP_MOVED_PERMANENTLY => 301;
  1         1  
  1         52  
17 1     1   5 use constant HTTP_MOVED_TEMPORARILY => 302;
  1         2  
  1         42  
18 1     1   5 use constant HTTP_REDIRECT => 302;
  1         11  
  1         60  
19 1     1   6 use constant HTTP_NOT_MODIFIED => 304;
  1         2  
  1         47  
20              
21 1     1   5 use constant HTTP_BAD_REQUEST => 400;
  1         18  
  1         54  
22 1     1   6 use constant HTTP_UNAUTHORIZED => 401;
  1         1  
  1         61  
23 1     1   6 use constant HTTP_PAYMENT_REQUIRED => 402;
  1         2  
  1         87  
24 1     1   6 use constant HTTP_FORBIDDEN => 403;
  1         2  
  1         56  
25 1     1   6 use constant HTTP_NOT_FOUND => 404;
  1         1  
  1         42  
26 1     1   5 use constant HTTP_NOT_ALLOWED => 405;
  1         2  
  1         49  
27 1     1   5 use constant HTTP_NOT_ACCEPTABLE => 406;
  1         2  
  1         52  
28 1     1   6 use constant HTTP_REQUEST_TIME_OUT => 408;
  1         1  
  1         41  
29 1     1   6 use constant HTTP_CONFLICT => 409;
  1         1  
  1         56  
30 1     1   23 use constant HTTP_GONE => 410;
  1         2  
  1         64  
31 1     1   6 use constant HTTP_LENGTH_REQUIRED => 411;
  1         1  
  1         53  
32 1     1   4 use constant HTTP_REQUEST_ENTITY_TOO_LARGE => 413;
  1         2  
  1         55  
33 1     1   6 use constant HTTP_REQUEST_URI_TOO_LARGE => 414;
  1         2  
  1         45  
34 1     1   5 use constant HTTP_UNSUPPORTED_MEDIA_TYPE => 415;
  1         20  
  1         57  
35 1     1   5 use constant HTTP_RANGE_NOT_SATISFIABLE => 416;
  1         2  
  1         42  
36              
37 1     1   5 use constant HTTP_INTERNAL_SERVER_ERROR => 500;
  1         2  
  1         47  
38 1     1   5 use constant HTTP_SERVER_ERROR => 500;
  1         2  
  1         51  
39 1     1   6 use constant HTTP_NOT_IMPLEMENTED => 501;
  1         1  
  1         80  
40 1     1   6 use constant HTTP_BAD_GATEWAY => 502;
  1         1  
  1         110  
41 1     1   14 use constant HTTP_SERVICE_UNAVAILABLE => 503;
  1         2  
  1         62  
42 1     1   6 use constant HTTP_GATEWAY_TIME_OUT => 504;
  1         2  
  1         49  
43 1     1   8 use constant HTTP_INSUFFICIENT_STORAGE => 507;
  1         1  
  1         71  
44              
45 1     1   510 use Drogo::Cookie;
  1         2  
  1         26  
46 1     1   303 use Drogo::MultiPart;
  1         3  
  1         34  
47              
48 1     1   512 use Time::HiRes qw(gettimeofday tv_interval);
  1         997  
  1         5  
49              
50 1     1   1028 BEGIN { require 5.008004; }
51              
52             # Export all @HTTP_STATUS_CODES
53             our @EXPORT = qw(
54             OK
55             DECLINED
56              
57             HTTP_OK
58             HTTP_CREATED
59             HTTP_ACCEPTED
60             HTTP_NO_CONTENT
61             HTTP_PARTIAL_CONTENT
62              
63             HTTP_MOVED_PERMANENTLY
64             HTTP_MOVED_TEMPORARILY
65             HTTP_REDIRECT
66             HTTP_NOT_MODIFIED
67              
68             HTTP_BAD_REQUEST
69             HTTP_UNAUTHORIZED
70             HTTP_PAYMENT_REQUIRED
71             HTTP_FORBIDDEN
72             HTTP_NOT_FOUND
73             HTTP_NOT_ALLOWED
74             HTTP_NOT_ACCEPTABLE
75             HTTP_REQUEST_TIME_OUT
76             HTTP_CONFLICT
77             HTTP_GONE
78             HTTP_LENGTH_REQUIRED
79             HTTP_REQUEST_ENTITY_TOO_LARGE
80             HTTP_REQUEST_URI_TOO_LARGE
81             HTTP_UNSUPPORTED_MEDIA_TYPE
82             HTTP_RANGE_NOT_SATISFIABLE
83              
84             HTTP_INTERNAL_SERVER_ERROR
85             HTTP_SERVER_ERROR
86             HTTP_NOT_IMPLEMENTED
87             HTTP_BAD_GATEWAY
88             HTTP_SERVICE_UNAVAILABLE
89             HTTP_GATEWAY_TIME_OUT
90             HTTP_INSUFFICIENT_STORAGE
91              
92             dispatch
93             );
94              
95             $SIG{__DIE__} = sub { &format_error(shift) };
96              
97             # data for request
98             my %request_data;
99             my @error_stack;
100             my $die_error;
101              
102             =head1 NAME
103              
104             Drogo::Guts - Shared components used by framework.
105              
106             =head1 SYNOPSIS
107              
108             =cut
109              
110             my %request_meta_data;
111              
112             sub dispatch
113             {
114 15     15 0 99 my ($r, %params) = @_;
115 15         31 my $class = $params{class};
116 15         22 my $method = $params{method};
117 15         26 my $error = $params{error};
118 15         31 my $bless = $params{bless};
119 15         24 my $base_class = $params{base_class};
120 15         21 my $dispatch_url = $params{dispatch_url};
121 15   100     36 my $post_args = $params{post_args} || [ ];
122              
123             # perform server initialization magic
124 15         67 $r->initialize($r);
125              
126 15   50     189 %request_meta_data = (
      50        
      50        
      100        
      100        
      50        
127             call_class => $class,
128             call_method => $method || 'main',
129             error => $error || '',
130             bless => $bless || '',
131             base_class => $base_class || '',
132             dispatch_url => $dispatch_url || '',
133             post_args => ($post_args || [ ]),
134             server_class => ref($r),
135             );
136              
137 15         45 &_store_request_meta_data($r);
138              
139 15 50       42 unless ($method eq 'error')
140             {
141 15         23 @error_stack = ( );
142 15         26 $die_error = q[];
143             }
144              
145 15 50 33     170 return (not $error and $r and $r->can('process_request_method') and
146             $r->process_request_method(\&handle_request_body))
147             ? $r->server_return(OK)
148             : &init_dispatcher($r);
149             }
150              
151             sub cleanup
152             {
153 30 50   30 0 117 if ($request_data{request_parts})
154             {
155 0         0 for my $part (@{$request_data{request_parts}})
  0         0  
156             {
157 0 0       0 next unless $part->{fh};
158              
159             # close each open fh
160 0         0 eval { $part->{fh}->close };
  0         0  
161              
162             # unlink file
163 0         0 unlink($part->{tmp_file});
164             }
165             }
166             }
167              
168             =head1 METHODS
169              
170             =head3 $self->server
171              
172             Returns the server object.
173              
174             =cut
175              
176 56     56 1 152 sub server { $request_data{server_object} }
177 0     0 0 0 sub set_server { $request_data{server_object} = $_[1] }
178              
179             =head3 $self->uri
180              
181             Returns the uri.
182              
183             =cut
184              
185 0     0 1 0 sub uri { shift->server->uri }
186              
187             =head3 $self->module_url
188              
189             Returns the url associated with the module.
190              
191             =cut
192              
193             sub module_url
194             {
195 0     0 1 0 my $self = shift;
196              
197 0         0 my @parts = split('/', $request_meta_data{'dispatch_url'});
198 0         0 pop @parts;
199              
200 0         0 return join('/', @parts);
201             }
202              
203             =head3 $self->filename
204              
205             Returns the path filename.
206              
207             =cut
208              
209 0     0 1 0 sub filename { shift->server->filename }
210              
211             =head3 $self->request_method
212              
213             Returns the request_method.
214              
215             =cut
216              
217 0     0 1 0 sub request_method { shift->server->request_method }
218              
219             =head3 $self->remote_addr
220              
221             Returns the remote_addr.
222              
223             =cut
224              
225 0     0 1 0 sub remote_addr { shift->server->remote_addr }
226              
227             =head3 $self->header_in
228              
229             Return value of header_in.
230              
231             =cut
232              
233 0     0 1 0 sub header_in { shift->server->header_in(@_) }
234              
235 15     15 0 31 sub rflush { shift->server->rflush }
236 15     15 0 35 sub flush { shift->rflush }
237              
238              
239             =head3 $self->print(...)
240              
241             Output via http.
242              
243             =cut
244              
245             sub print
246             {
247 13     13 1 79 my $self = shift;
248              
249 13         45 $request_data{output} .= join '', @_;
250 13         77 return 1;
251             }
252              
253             =head3 $self->auto_header
254              
255             Returns true if set, otherwise args 1 sets true and 0 false.
256              
257             =cut
258              
259             sub auto_header
260             {
261 15     15 1 29 my ($self, $arg) = @_;
262              
263 15 50       32 if (defined $arg)
264             {
265 0 0       0 if ($arg)
266             {
267 0         0 delete $request_data{disable_auto_header};
268             }
269             else
270             {
271 0         0 $request_data{disable_auto_header} = 1;
272             }
273             }
274              
275 15         58 return(not exists $request_data{disable_auto_header});
276             }
277              
278             =head3 $self->dispatching
279              
280             Returns true if we're dispatching actively.
281              
282             =cut
283              
284             sub dispatching
285             {
286 45     45 1 80 my ($self, $arg) = @_;
287              
288 45 50       124 if (defined $arg)
289             {
290 0 0       0 if ($arg)
291             {
292 0         0 delete $request_data{disable_dispatching};
293             }
294             else
295             {
296 0         0 $request_data{disable_dispatching} = 1;
297             }
298             }
299              
300 45         181 return(not exists $request_data{disable_dispatching});
301             }
302              
303             =head3 $self->header_set('header_type', 'value')
304              
305             Set output header.
306              
307             =cut
308              
309             sub header_set
310             {
311 0     0 1 0 my ($self, $key, $value) = @_;
312              
313 0         0 $request_data{headers}{$key} = $value;
314             }
315              
316             =head3 $self->header('content-type')
317              
318             Set content type.
319              
320             =cut
321              
322             sub header
323             {
324 0     0 1 0 my ($self, $value) = @_;
325              
326 0         0 __PACKAGE__->header_set('Content-Type', $value);
327             }
328              
329             =head3 $self->headers
330              
331             Returns hashref of response headers.
332              
333             =cut
334              
335             sub headers
336             {
337 0     0 1 0 my ($self, $value) = @_;
338              
339 0         0 return $request_data{headers};
340             }
341              
342             =head3 $self->location('url')
343              
344             Redirect to a url (sets the Location header out).
345              
346             =cut
347              
348 0     0 1 0 sub location { shift->header_set('Location', shift) }
349              
350             =head3 $self->status(...)
351              
352             Set output status... (200, 404, etc...)
353             If no argument given, returns status.
354              
355             =cut
356              
357             sub status
358             {
359 17     17 1 53 my ($self, $status) = @_;
360              
361 17 100       28 if ($status)
362             {
363 2         15 $request_data{status} = $status;
364             }
365             else
366             {
367 15         99 return $request_data{status};
368             }
369             }
370              
371             # map $self->log to print STDERR
372 0     0 0 0 sub log { shift; print STDERR @_; }
  0         0  
373              
374             =head3 $self->request_part(...)
375              
376             Returns reference for upload.
377              
378             {
379             'filename' => 'filename',
380             'tmp_file' => '/tmp/drogomp-23198-1330057261',
381             'fh' => \*{'Drogo::MultiPart::$request_part{...}'},
382             'name' => 'foo'
383             }
384              
385             =cut
386              
387             sub request_part
388             {
389 0     0 1 0 my ($self, $lookup_key) = @_;
390 0         0 my @values;
391              
392 0 0       0 if ($request_data{request_parts})
393             {
394 0         0 for my $part (@{$request_data{request_parts}})
  0         0  
395             {
396 0 0       0 push @values, $part if $lookup_key eq $part->{name};
397             }
398             }
399              
400 0 0       0 return unless @values;
401 0 0       0 return (scalar @values == 1 ? $values[0] : @values);
402             }
403              
404             =head3 $self->param(...)
405              
406             Return a parameter passed via CGI--works like CGI::param.
407              
408             =cut
409             warn 'drogo';
410             sub param
411             {
412 0     0 1 0 my ($self, $lookup_key) = @_;
413            
414 0         0 my @values;
415             my %seen_hash;
416 0         0 my $request = $request_data{args};
417              
418 1     1   525 use Data::Dumper;
  1         6665  
  1         606  
419 0         0 warn Dumper \%request_data;
420            
421 0 0       0 if ($request_data{request_parts})
422             {
423 0         0 for my $part (@{$request_data{request_parts}})
  0         0  
424             {
425             # don't return uploads here
426 0 0       0 next if $part->{fh};
427              
428 0 0       0 if ($lookup_key)
429             {
430             push @values, $part->{data}
431 0 0       0 if $lookup_key eq $part->{name};
432             }
433             else
434             {
435 0 0       0 next if $seen_hash{$part->{name}}++;
436 0         0 push @values, $part->{name};
437             }
438             }
439             }
440             else
441             {
442 0         0 my @args = split('&', $request);
443 0         0 for my $arg (@args)
444             {
445 0         0 my ($key, $value) = split('=', $arg);
446            
447 0 0       0 if ($lookup_key)
448             {
449 0 0       0 push @values, __PACKAGE__->unescape($value)
450             if $lookup_key eq $key;
451             }
452             else
453             {
454 0 0       0 next if $seen_hash{$key}++;
455 0         0 push @values, $key;
456             }
457             }
458             }
459            
460 0 0       0 return unless @values;
461            
462 0 0       0 return (scalar @values == 1 ? $values[0] : @values);
463             }
464              
465             =head3 $self->param_hash
466            
467             Return a friendly hashref of CGI parameters.
468              
469             =cut
470              
471             sub param_hash
472             {
473 0     0 1 0 my $self = shift;
474              
475 0         0 my %param_hash;
476            
477 0         0 for my $key (__PACKAGE__->param)
478             {
479 0 0       0 next if $param_hash{$key};
480            
481 0         0 my @params = __PACKAGE__->param($key);
482            
483 0 0       0 if (scalar @params == 1)
484             {
485 0         0 $param_hash{$key} = $params[0];
486             }
487             else
488             {
489 0         0 $param_hash{$key} = [ @params ],
490             }
491             }
492            
493 0         0 return \%param_hash;
494             }
495              
496             =head3 $self->request_body & $self->request
497            
498             Returns request body.
499              
500             =cut
501              
502 0     0 1 0 sub request_body { $request_data{request} }
503 0     0 1 0 sub request { shift->request_body }
504              
505             =head3 $self->request_parts
506              
507             Returns arrayref of request parts, used for multipart/form-data requests.
508              
509             =cut
510              
511 0 0   0 1 0 sub request_parts { $request_data{request_parts} || [] }
512              
513             =head3 $self->args
514              
515             Returns args.
516              
517             =cut
518              
519 0     0 1 0 sub args { $request_data{args} }
520              
521             =head3 $self->matches
522              
523             Returns array of post_arguments (matching path after a matched ActionMatch attribute)
524             Returns array of matching elements when used with ActionRegex.
525              
526             =cut
527              
528 0 0   0 1 0 sub matches { @{ $request_data{post_args} || [ ] } }
  0         0  
529              
530             =head3 $self->post_args
531              
532             Same as matches, deprecated.
533              
534             =cut
535              
536 5 50   5 1 38 sub post_args { @{ $request_data{post_args} || [ ] } }
  5         27  
537              
538             sub handle_request_body
539             {
540 0     0 0 0 my $r = shift;
541              
542             # reinflate $r if necessary
543 0         0 &_inflate_request_meta_data($r);
544 0 0       0 if (ref($r) ne $request_meta_data{server_class})
545             {
546 0         0 my $server_class = $request_meta_data{server_class};
547 0         0 $server_class->initialize($r);
548             }
549              
550 0         0 my $request_body = $r->request_body;
551 0         0 my %params;
552              
553             # if no args are passed, assume they are in the post
554 0 0 0     0 if (not $r->args and
      0        
555             substr($request_body, 0, 1) ne '{' and
556             index($request_body, "\n") == -1)
557             {
558 0         0 $params{args} = $request_body;
559             }
560             else # process multi-line data
561             {
562             # decode multi-part data
563 0 0       0 $params{request_parts} = Drogo::MultiPart::process($r)
564             if substr($request_body, 0, 1) eq '-';
565             }
566              
567 0         0 return &init_dispatcher($r, %params);
568             }
569              
570             sub init_dispatcher {
571 15     15 0 33 my ($r, %params) = @_;
572              
573             %request_data = (
574             headers => { 'Content-Type' => 'text/html' },
575             output => q[],
576             status => 200,
577             server_object => $r,
578             request => $params{request} || $r->request_body,
579             args => $params{args} || $r->args,
580             request_parts => $params{request_parts},
581             begin_time => [gettimeofday],
582             post_args => $request_meta_data{post_args},
583 15   33     88 );
      33        
584              
585 15         35 my $class = $request_meta_data{'call_class'};
586 15         56 my $bless = $request_meta_data{'bless'};
587 15         26 my $base_class = $request_meta_data{'base_class'};
588 15         24 my $method = $request_meta_data{'call_method'};
589              
590 15         20 my $self = { };
591 15 50       59 $bless ? bless($self, $class) : bless($self);
592              
593 15         31 my $sub_call = "$class\::$method";
594 15 50       71 if (UNIVERSAL::can($class, $method))
595             {
596 1     1   7 no strict 'refs';
  1         1  
  1         56  
597              
598             # pre-run sub, if defined
599 15   66     42 my $init_class = $base_class || $class;
600 15 50 33     61 if (UNIVERSAL::can($init_class, 'init') and not $method eq 'error')
601             {
602 1     1   4 no strict 'refs';
  1         1  
  1         127  
603 0         0 eval {
604 0     0   0 local $SIG{__DIE__} = sub { &format_error(shift) };
  0         0  
605 0 0       0 if ($bless)
606             {
607 0         0 $self->init;
608             }
609             else
610             {
611 0         0 my $prerun_sub = "$init_class\::init";
612 0         0 $prerun_sub->($self);
613             }
614             };
615              
616 0 0 0     0 if ($@ and $@ ne "drogo-exit\n")
617             {
618 0 0       0 if ($method eq 'error')
619             {
620             # you've got an error in your error handler
621 0         0 warn "Error in error handler... ($class\::error)\n";
622              
623 0         0 return __PACKAGE__->init_error($sub_call);
624             }
625              
626             # reset request data
627             %request_data = (
628             %request_data,
629             headers => { 'Content-Type' => 'text/html' },
630             output => q[],
631             status => 200,
632             server_object => $r,
633             request => $params{request} || $r->request_body,
634             args => $params{args} || $r->args,
635             request_parts => $params{request_parts},
636 0   0     0 );
      0        
637              
638 0         0 eval {
639 1     1   3 no strict 'refs';
  1         2  
  1         173  
640 0     0   0 local $SIG{__DIE__} = sub { &format_error(shift) };
  0         0  
641 0 0       0 if ($bless)
642             {
643 0         0 $self->error;
644             }
645             else
646             {
647 0         0 my $prerun_sub = "$init_class\::error";
648 0         0 $prerun_sub->($self);
649             }
650             };
651              
652 0 0 0     0 if ($@ and $@ ne "drogo-exit\n")
653             {
654 0 0       0 if ($method eq 'error')
655             {
656             # you've got an error in your error handler
657 0         0 warn "Error in error handler... ($class\::error)\n";
658              
659 0         0 return __PACKAGE__->init_error($sub_call);
660             }
661             }
662             else
663             {
664 0 0 0     0 __PACKAGE__->process_auto_header
665             if __PACKAGE__->auto_header and __PACKAGE__->dispatching;
666              
667             # cleanup drogo internals from dispatch
668 0         0 &cleanup($r);
669 0         0 $r->cleanup;
670              
671 0         0 return $r->server_return(OK);
672             }
673             }
674             }
675              
676 15         25 my $error = $request_meta_data{'error'};
677              
678 15 50       51 if (__PACKAGE__->dispatching)
679             {
680 15         22 eval {
681 1     1   4 no strict 'refs';
  1         1  
  1         132  
682 15     0   129 local $SIG{__DIE__} = sub { &format_error(shift) };
  0         0  
683              
684 15         25 my @args;
685 15 50       30 push @args, $error if $error;
686              
687 15 50       28 if ($bless)
688             {
689 15         66 $self->$method(@args);
690             }
691             else
692             {
693 0         0 $sub_call->($self, @args);
694             }
695             };
696              
697 15 50 33     61 if ($@ and $@ ne "drogo-exit\n")
698             {
699 0 0       0 if ($method eq 'error')
700             {
701             # you've got an error in your error handler
702 0         0 warn "Error in error handler... ($class\::error)\n";
703              
704 0         0 return __PACKAGE__->init_error($sub_call);
705             }
706              
707             # reset request data
708             %request_data = (
709             %request_data,
710             headers => { 'Content-Type' => 'text/html' },
711             output => q[],
712             status => 200,
713             server_object => $r,
714             request => $params{request} || $r->request_body,
715             args => $params{args} || $r->args,
716             request_parts => $params{request_parts},
717 0   0     0 );
      0        
718              
719 0         0 eval {
720 1     1   4 no strict 'refs';
  1         1  
  1         158  
721 0     0   0 local $SIG{__DIE__} = sub { &format_error(shift) };
  0         0  
722 0 0       0 if ($bless)
723             {
724 0         0 $self->error;
725             }
726             else
727             {
728 0         0 my $prerun_sub = "$init_class\::error";
729 0         0 $prerun_sub->($self);
730             }
731             };
732              
733 0 0 0     0 if ($@ and $@ ne "drogo-exit\n")
734             {
735 0 0       0 if ($method eq 'error')
736             {
737             # you've got an error in your error handler
738 0         0 warn "Error in error handler... ($class\::error)\n";
739              
740 0         0 return __PACKAGE__->init_error($sub_call);
741             }
742             }
743             else
744             {
745 0 0 0     0 __PACKAGE__->process_auto_header
746             if __PACKAGE__->auto_header and __PACKAGE__->dispatching;
747              
748             # cleanup drogo internals from dispatch
749 0         0 &cleanup($r);
750 0         0 $r->cleanup;
751              
752 0         0 return $r->server_return(OK);
753             }
754             }
755             else
756             {
757             # process all data
758 15 50 33     34 __PACKAGE__->process_auto_header
759             if __PACKAGE__->auto_header and __PACKAGE__->dispatching;
760              
761             # post-run sub, if defined
762 15   66     54 my $cleanup_class = $base_class || $class;
763 15 50 33     131 if (UNIVERSAL::can($cleanup_class, 'cleanup') and $method ne 'error'
      33        
764             and __PACKAGE__->dispatching)
765             {
766 15         21 eval {
767 1     1   4 no strict 'refs';
  1         1  
  1         848  
768 15     0   103 local $SIG{__DIE__} = sub { &format_error(shift) };
  0         0  
769 15 50       32 if ($bless)
770             {
771 15         51 $self->cleanup;
772             }
773             else
774             {
775 0         0 my $cleanup_sub = "$cleanup_class\::cleanup";
776 0         0 $cleanup_sub->($self);
777             }
778             };
779             }
780             }
781             }
782              
783 15         50 undef $self;
784              
785             # cleanup drogo internals from dispatch
786 15         36 &cleanup($r);
787 15         57 $r->cleanup;
788              
789 15         36 return $r->server_return(OK);
790             }
791             else
792             {
793 0         0 return __PACKAGE__->init_error($r, $sub_call);
794             }
795             }
796              
797             =head3 detach
798              
799             Stops processing and "exits"
800              
801             =cut
802              
803 0     0 1 0 sub detach { die "drogo-exit\n" }
804              
805             =head3 process_auto_header
806              
807             Process the autoheader.
808              
809             =cut
810              
811             sub process_auto_header
812             {
813 15     15 1 23 my $self = shift;
814              
815 15         34 __PACKAGE__->server->status($self->status);
816            
817 15         36 my $content_type = delete $request_data{headers}{'Content-Type'};
818              
819             __PACKAGE__->server->header_out($_, $request_data{headers}{$_})
820 15         22 for keys %{$request_data{headers}};
  15         50  
821              
822 15         60 __PACKAGE__->server->send_http_header($content_type);
823              
824 15         31 $request_data{headers}{'Content-Type'} = $content_type;
825              
826 15         2955 open(my $ofh, '<', \$request_data{output});
827 15         33 my $buffer;
828 15         72 while (read($ofh, $buffer, 1024))
829             {
830 11         49 __PACKAGE__->server->print($buffer);
831             }
832 15         43 close($ofh);
833              
834 15         47 __PACKAGE__->flush;
835             }
836              
837             sub format_error
838             {
839 0     0 0 0 my $error = shift;
840 0         0 my @stack = &make_error_stack;
841 0         0 $die_error = $error;
842              
843 0 0       0 return if $error eq "drogo-exit\n";
844              
845 0         0 warn $error;
846              
847 0         0 for my $e (@stack)
848             {
849 0         0 warn "$e->{sub} called at $e->{file} line $e->{line}\n";
850             }
851             }
852              
853             =head3 error_stack
854              
855             Returns the "error stack" as an array.
856              
857             =cut
858              
859 0     0 1 0 sub error_stack { @error_stack };
860              
861             =head3 get_error
862              
863             Returns error as string.
864              
865             =cut
866              
867 0     0 1 0 sub get_error { $die_error };
868              
869             sub make_error_stack
870             {
871 0     0 0 0 my @stack;
872 0         0 my $i = 0;
873 0         0 while (my @x = caller(++$i)) {
874 0         0 push @stack, {
875             pack => $x[0],
876             file => $x[1],
877             line => $x[2],
878             sub => $x[3],
879             };
880             }
881              
882 0         0 shift @stack;
883 0         0 shift @stack;
884 0         0 pop @stack;
885              
886 0         0 @error_stack = @stack;
887              
888 0         0 return @stack;
889             }
890              
891             sub init_error
892             {
893 0     0 0 0 my ($self, $r, $sub) = @_;
894            
895             # cleanup drogo internals from dispatch
896 0         0 &cleanup($r);
897 0         0 $r->cleanup;
898              
899 0 0       0 warn(__PACKAGE__ . qq[: '$sub' does not exist...\n])
900             unless $sub =~ /error$/;
901              
902 0         0 return $r->server_return(HTTP_SERVER_ERROR);
903             }
904              
905             =head3 $self->unescape
906              
907             Unscape HTTP URI encoding.
908              
909             =cut
910              
911             sub unescape
912             {
913 0     0 1 0 my ($self, $value) = @_;
914              
915 0         0 $value =~ s/\+/ /g;
916 0         0 $value = __PACKAGE__->server->unescape($value);
917              
918 0         0 return $value;
919             }
920              
921             =head3 $self->cookie
922              
923             Cookie methods:
924              
925             $self->cookie->set(-name => 'foo', -value => 'bar');
926             my %cookies = $self->cookie->read;
927              
928             =cut
929              
930 0     0 1 0 sub cookie { new Drogo::Cookie(shift) }
931              
932             =head3 $self->elapsed_time
933              
934             Returns elapsed time since initial dispatch.
935              
936             =cut
937              
938 0     0 1 0 sub elapsed_time { tv_interval($request_data{begin_time}, [gettimeofday]) }
939              
940              
941              
942             sub _store_request_meta_data
943             {
944 15     15   37 my $r = shift;
945              
946             # nginx needs to pass this data between threads
947             $r->variable( $_ => $request_meta_data{$_} )
948 15         100 for qw(call_class call_method error bless base_class dispatch_url server_class);
949              
950             # dragons
951 15 50       23 $r->variable( post_args => join('|', @{$request_meta_data{post_args} || [ ]}) );
  15         92  
952             }
953              
954             sub _inflate_request_meta_data
955             {
956 0     0     my $r = shift;
957 0           %request_meta_data = ( );
958             $request_meta_data{$_} = $r->variable($_)
959 0           for qw(call_class call_method error bless base_class dispatch_url server_class);
960             $request_meta_data{post_args} =
961 0           [ split(/\|/, $r->variable('post_args')) ];
962             }
963              
964             =head1 AUTHORS
965              
966             Bizowie
967              
968             =head1 COPYRIGHT AND LICENSE
969              
970             Copyright (C) 2013 Bizowie
971              
972             This library is free software. You can redistribute it and/or modify it under the same terms as Perl itself.
973              
974             =cut
975              
976             1;