Imported Upstream version 3.12
Xavier Guimard
11 years ago
27 | 27 | 'Plack' => 0.9956, # really, we just depend on Plack::Test, but Plack::Test has not declared a version. |
28 | 28 | $have_apache_test ? ( 'Apache::Test' => 0 ) : (), |
29 | 29 | }, |
30 | meta_merge => { | |
31 | resources => { | |
32 | repository => 'https://github.com/markstos/CGI--Application--Dispatch', | |
33 | }, | |
34 | }, | |
30 | 35 | ); |
31 | 36 | |
32 | 37 | $build->create_build_script; |
0 | 0 | Revision history for Perl extension CGI::Application::Dispatch. |
1 | ||
2 | 3.12 September 10th, 2012 | |
3 | [BUG FIXES] | |
4 | - Further fix diagnostic message in some cases when exceptions are thrown. (Michael Lackhoff) | |
5 | ||
6 | 3.11 September 10th, 2012 | |
7 | (No code changes) | |
8 | ||
9 | [INTERNALS] | |
10 | - Fixed test for rethrowing HTTP::Exception objects (Graham TerMarsch) | |
11 | ||
12 | 3.10 September 2nd, 2012 | |
13 | [NEW FEATURES] | |
14 | - CGI::Application::Dispatch::PSGI now allows exceptions thrown as HTTP::Exception objects | |
15 | to bubble up in some cases. See the new documentation section on "Exception Handling" | |
16 | for details. (Mark Stosberg, Graham TerMarsch, RT#79022) | |
17 | ||
18 | [BUG FIXES] | |
19 | - When auto_rest was enabled and no run mode was found, a 404 could have been returned | |
20 | instead of defaulting to start mode. We now correctly default to the start_mode(). | |
21 | (James Q.L., Ron Savage, Mark Stosberg) | |
22 | ||
23 | [DOCUMENTATION] | |
24 | - Docs have been expanded to explain how /foo/:rm? resolves, and interaction | |
25 | with start_mode() when no run mode is found. (Mark Stosberg) | |
26 | ||
27 | [INTERNALS] | |
28 | - Fix diagnostic message in some cases when exceptions are thrown (Michael Lackhoff) | |
29 | - Added test coverage for auto_rest to CGI::Application::Dispatch::PSGI (Mark Stosberg) | |
30 | - POD formatting fix in Dispatch.pm | |
31 | - Fix Perl 5.14 compatibility warning (chorny, RENEEB@cpan.org, SILASMONK@cpan.org) | |
1 | 32 | |
2 | 33 | 3.07 September 9th, 2011 |
3 | 34 | Fix t/cgi.t test failures caused by Try::Tiny refactor in 3.05 (Yoshihiro Sasaki) |
3 | 3 | "Michael Peters <mpeters@plusthree.com>" |
4 | 4 | ], |
5 | 5 | "dynamic_config" : 1, |
6 | "generated_by" : "Module::Build version 0.38, CPAN::Meta::Converter version 2.110930", | |
6 | "generated_by" : "Module::Build version 0.4003, CPAN::Meta::Converter version 2.112150", | |
7 | 7 | "license" : [ |
8 | 8 | "perl_5" |
9 | 9 | ], |
40 | 40 | "provides" : { |
41 | 41 | "CGI::Application::Dispatch" : { |
42 | 42 | "file" : "lib/CGI/Application/Dispatch.pm", |
43 | "version" : "3.07" | |
43 | "version" : "3.12" | |
44 | 44 | }, |
45 | 45 | "CGI::Application::Dispatch::PSGI" : { |
46 | 46 | "file" : "lib/CGI/Application/Dispatch/PSGI.pm", |
47 | "version" : "3.04" | |
47 | "version" : "3.12" | |
48 | 48 | }, |
49 | 49 | "CGI::Application::Dispatch::Regexp" : { |
50 | 50 | "file" : "lib/CGI/Application/Dispatch/Regexp.pm", |
55 | 55 | "resources" : { |
56 | 56 | "license" : [ |
57 | 57 | "http://dev.perl.org/licenses/" |
58 | ] | |
58 | ], | |
59 | "repository" : { | |
60 | "url" : "https://github.com/markstos/CGI--Application--Dispatch" | |
61 | } | |
59 | 62 | }, |
60 | "version" : "3.07" | |
63 | "version" : "3.12" | |
61 | 64 | } |
9 | 9 | configure_requires: |
10 | 10 | Module::Build: 0.38 |
11 | 11 | dynamic_config: 1 |
12 | generated_by: 'Module::Build version 0.38, CPAN::Meta::Converter version 2.110930' | |
12 | generated_by: 'Module::Build version 0.4003, CPAN::Meta::Converter version 2.112150' | |
13 | 13 | license: perl |
14 | 14 | meta-spec: |
15 | 15 | url: http://module-build.sourceforge.net/META-spec-v1.4.html |
18 | 18 | provides: |
19 | 19 | CGI::Application::Dispatch: |
20 | 20 | file: lib/CGI/Application/Dispatch.pm |
21 | version: 3.07 | |
21 | version: 3.12 | |
22 | 22 | CGI::Application::Dispatch::PSGI: |
23 | 23 | file: lib/CGI/Application/Dispatch/PSGI.pm |
24 | version: 3.04 | |
24 | version: 3.12 | |
25 | 25 | CGI::Application::Dispatch::Regexp: |
26 | 26 | file: lib/CGI/Application/Dispatch/Regexp.pm |
27 | 27 | version: 3.04 |
34 | 34 | version: 0.82 |
35 | 35 | resources: |
36 | 36 | license: http://dev.perl.org/licenses/ |
37 | version: 3.07 | |
37 | repository: https://github.com/markstos/CGI--Application--Dispatch | |
38 | version: 3.12 |
0 | 0 | package CGI::Application::Dispatch::PSGI; |
1 | 1 | use strict; |
2 | 2 | use warnings; |
3 | use Carp qw(carp cluck); | |
3 | use Carp 'carp'; | |
4 | 4 | use HTTP::Exception; |
5 | use Try::Tiny; | |
6 | ||
7 | our $VERSION = '3.04'; | |
5 | ||
6 | our $VERSION = '3.12'; | |
8 | 7 | our $DEBUG = 0; |
9 | 8 | |
10 | 9 | =pod |
11 | 10 | |
12 | 11 | =head1 NAME |
13 | 12 | |
14 | CGI::Application::Dispatch::PSGI - Dispatch requests to CGI::Application based objects using PSGI | |
13 | CGI::Application::Dispatch::PSGI - Dispatch requests to | |
14 | CGI::Application based objects using PSGI | |
15 | 15 | |
16 | 16 | =head1 SYNOPSIS |
17 | 17 | |
69 | 69 | |
70 | 70 | =head2 With a custom query object |
71 | 71 | |
72 | If you want to supply your own PSGI object, something like this in your .psgi file will work: | |
72 | If you want to supply your own PSGI object, something like this in | |
73 | your .psgi file will work: | |
73 | 74 | |
74 | 75 | sub { |
75 | 76 | my $env = shift; |
87 | 88 | |
88 | 89 | =head1 DESCRIPTION |
89 | 90 | |
90 | This module provides a way to look at the path (as returned by | |
91 | C<< $env->{PATH_INFO} >>) of the incoming request, parse off the desired module and | |
92 | its run mode, create an instance of that module and run it. | |
91 | This module provides a way to look at the path (as returned by C<< | |
92 | $env->{PATH_INFO} >>) of the incoming request, parse off the desired | |
93 | module and its run mode, create an instance of that module and run it. | |
93 | 94 | |
94 | 95 | It will translate a URI like this (in a persistent environment) |
95 | 96 | |
190 | 191 | # use the 'default' if we need to |
191 | 192 | $path_info = $args{default} || '' if(!$path_info || $path_info eq '/'); |
192 | 193 | |
193 | # make sure they all start and end with a '/', to correspond with the RE we'll make | |
194 | # make sure they all start and end with a '/', to correspond | |
195 | # with the RE we'll make | |
194 | 196 | $path_info = "/$path_info" unless(index($path_info, '/') == 0); |
195 | 197 | $path_info = "$path_info/" unless(substr($path_info, -1) eq '/'); |
196 | 198 | |
243 | 245 | |
244 | 246 | my $auto_rest = |
245 | 247 | defined $named_args->{auto_rest} ? $named_args->{auto_rest} : $args{auto_rest}; |
246 | if($auto_rest) { | |
248 | if($auto_rest && defined $rm && length $rm) { | |
247 | 249 | my $method_lc = |
248 | 250 | defined $named_args->{auto_rest_lc} |
249 | 251 | ? $named_args->{auto_rest_lc} |
258 | 260 | $psgi_app = $self->_run_app($module, $rm, $local_args_to_new,$env); |
259 | 261 | }; |
260 | 262 | if (my $e = HTTP::Exception->caught) { |
261 | # XXX I think this is a bug, because http_error returns HTML, not a PSGI app. | |
262 | 263 | return $self->http_error($e); |
263 | 264 | } |
264 | 265 | elsif ($e = Exception::Class->caught) { |
292 | 293 | |
293 | 294 | =item prefix |
294 | 295 | |
295 | This option will set the string that will be prepended to the name of the application | |
296 | module before it is loaded and created. So to use our previous example request of | |
296 | This option will set the string that will be prepended to the name of | |
297 | the application module before it is loaded and created. So to use our | |
298 | previous example request of | |
297 | 299 | |
298 | 300 | /app/index.cgi/module_name/run_mode |
299 | 301 | |
300 | This would by default load and create a module named 'Module::Name'. But let's say that you | |
301 | have all of your application specific modules under the 'My' namespace. If you set this option | |
302 | to 'My' then it would instead load the 'My::Module::Name' application module instead. | |
302 | This would by default load and create a module named | |
303 | 'Module::Name'. But let's say that you have all of your application | |
304 | specific modules under the 'My' namespace. If you set this option to | |
305 | 'My' then it would instead load the 'My::Module::Name' application | |
306 | module instead. | |
303 | 307 | |
304 | 308 | =item args_to_new |
305 | 309 | |
306 | This is a hash of arguments that are passed into the C<new()> constructor of the application. | |
310 | This is a hash of arguments that are passed into the C<new()> | |
311 | constructor of the application. | |
307 | 312 | |
308 | 313 | =item table |
309 | 314 | |
310 | In most cases, simply using Dispatch with the C<default> and C<prefix> is enough | |
311 | to simplify your application and your URLs, but there are many cases where you want | |
312 | more power. Enter the dispatch table. Since this table can be slightly complicated, | |
313 | a whole section exists on its use. Please see the L<DISPATCH TABLE> section. | |
315 | In most cases, simply using Dispatch with the C<default> and C<prefix> | |
316 | is enough to simplify your application and your URLs, but there are | |
317 | many cases where you want more power. Enter the dispatch table. Since | |
318 | this table can be slightly complicated, a whole section exists on its | |
319 | use. Please see the L<DISPATCH TABLE> section. | |
314 | 320 | |
315 | 321 | =item debug |
316 | 322 | |
317 | Set to a true value to send debugging output for this module to STDERR. Off by default. | |
323 | Set to a true value to send debugging output for this module to | |
324 | STDERR. Off by default. | |
318 | 325 | |
319 | 326 | =item auto_rest |
320 | 327 | |
321 | This tells Dispatch that you are using REST by default and that you care about which HTTP method | |
322 | is being used. Dispatch will append the HTTP method name (upper case by default) to | |
323 | the run mode that is determined after finding the appropriate dispatch rule. So a GET request | |
324 | that translates into C<< MyApp::Module->foo >> will become C<< MyApp::Module->foo_GET >>. | |
328 | This tells Dispatch that you are using REST by default and that you | |
329 | care about which HTTP method is being used. Dispatch will append the | |
330 | HTTP method name (upper case by default) to the run mode that is | |
331 | determined after finding the appropriate dispatch rule. So a GET | |
332 | request that translates into C<< MyApp::Module->foo >> will become | |
333 | C<< MyApp::Module->foo_GET >>. | |
325 | 334 | |
326 | 335 | This can be overridden on a per-rule basis in a custom dispatch table. |
327 | 336 | |
328 | 337 | =item auto_rest_lc |
329 | 338 | |
330 | In combinaion with L<auto_rest> this tells Dispatch that you prefer lower cased HTTP method names. | |
331 | So instead of C<foo_POST> and C<foo_GET> you'll have C<foo_post> and C<foo_get>. | |
339 | In combinaion with L<auto_rest> this tells Dispatch that you prefer | |
340 | lower cased HTTP method names. So instead of C<foo_POST> and | |
341 | C<foo_GET> you'll have C<foo_post> and C<foo_get>. | |
332 | 342 | |
333 | 343 | =back |
334 | 344 | |
344 | 354 | my $errno = $e->isa('HTTP::Exception::Base') ? $e->code : 500; |
345 | 355 | my $output = $e->isa('HTTP::Exception::Base') ? $e->status_message : "Internal Server Error"; |
346 | 356 | |
347 | # The custom status message was most useful for logging. Return generic messages to the user. | |
357 | # The custom status message was most useful for logging. Return | |
358 | # generic messages to the user. | |
348 | 359 | $output = 'Not Found' if ($e->code == 404); |
349 | 360 | $output = 'Internal Server Error' if ($e->code == 500); |
350 | 361 | |
381 | 392 | $rule =~ s/$http_method_regex//; |
382 | 393 | } |
383 | 394 | |
384 | # make sure they start and end with a '/' to match how PATH_INFO is formatted | |
395 | # make sure they start and end with a '/' to match how | |
396 | # PATH_INFO is formatted | |
385 | 397 | $rule = "/$rule" unless(index($rule, '/') == 0); |
386 | 398 | $rule = "$rule/" if(substr($rule, -1) ne '/'); |
387 | 399 | |
388 | 400 | my @names = (); |
389 | 401 | |
390 | # translate the rule into a regular expression, but remember where the named args are | |
402 | # translate the rule into a regular expression, but remember | |
403 | # where the named args are | |
391 | 404 | # '/:foo' will become '/([^\/]*)' |
392 | 405 | # and |
393 | 406 | # '/:bar?' will become '/?([^\/]*)?' |
446 | 459 | # now create and run then application object |
447 | 460 | warn "[Dispatch] creating instance of $module\n" if($DEBUG); |
448 | 461 | |
449 | try { | |
462 | my $psgi; | |
463 | eval { | |
450 | 464 | my $app = do { |
451 | 465 | if (ref($args) eq 'HASH' and not defined $args->{QUERY}) { |
452 | 466 | require CGI::PSGI; |
461 | 475 | } |
462 | 476 | }; |
463 | 477 | $app->mode_param(sub { return $rm }) if($rm); |
464 | return $app->run_as_psgi; | |
465 | } | |
466 | catch { | |
467 | # catch invalid run-mode stuff | |
468 | if(not ref $_ and $_ =~ /No such run mode/) { | |
469 | HTTP::Exception->throw(404, status_message => "RM '$rm' not found"); | |
470 | } | |
471 | # otherwise, just pass it up the chain | |
472 | else { | |
473 | HTTP::Exception->throw(500, status_message => "Unknown error: $_"); | |
474 | } | |
478 | $psgi = $app->run_as_psgi; | |
475 | 479 | }; |
480 | ||
481 | # App threw an HTTP::Exception? Cool. Bubble it up. | |
482 | my $e; | |
483 | if ($e = HTTP::Exception->caught) { | |
484 | $e->rethrow; | |
485 | } | |
486 | else { | |
487 | $e = Exception::Class->caught(); | |
488 | ||
489 | # catch invalid run-mode stuff | |
490 | if (not ref $e and $e =~ /No such run mode/) { | |
491 | HTTP::Exception->throw(404, status_message => "RM '$rm' not found"); | |
492 | } | |
493 | # otherwise, it's an internal server error. | |
494 | elsif (defined $e and length $e) { | |
495 | HTTP::Exception->throw(500, status_message => "Unknown error: $e"); | |
496 | #return $psgi; | |
497 | } | |
498 | else { | |
499 | # no exception | |
500 | return $psgi; | |
501 | } | |
502 | } | |
476 | 503 | } |
477 | 504 | |
478 | 505 | =head2 dispatch_args() |
479 | 506 | |
480 | Returns a hashref of args that will be passed to L<dispatch>(). It will return the following | |
481 | structure by default. | |
507 | Returns a hashref of args that will be passed to L<dispatch>(). It | |
508 | will return the following structure by default. | |
482 | 509 | |
483 | 510 | { |
484 | 511 | prefix => '', |
489 | 516 | ], |
490 | 517 | } |
491 | 518 | |
492 | This is the perfect place to override when creating a subclass to provide a richer dispatch | |
493 | L<table>. | |
494 | ||
495 | When called, it receives 1 argument, which is a reference to the hash of args passed into | |
496 | L<dispatch>. | |
519 | This is the perfect place to override when creating a subclass to | |
520 | provide a richer dispatch L<table>. | |
521 | ||
522 | When called, it receives 1 argument, which is a reference to the hash | |
523 | of args passed into L<dispatch>. | |
497 | 524 | |
498 | 525 | =cut |
499 | 526 | |
513 | 540 | =head2 translate_module_name($input) |
514 | 541 | |
515 | 542 | This method is used to control how the module name is translated from |
516 | the matching section of the path (see L<"Path Parsing">. | |
517 | The main reason that this method exists is so that it can be overridden if it doesn't do | |
518 | exactly what you want. | |
543 | the matching section of the path (see L<"Path Parsing">. The main | |
544 | reason that this method exists is so that it can be overridden if it | |
545 | doesn't do exactly what you want. | |
519 | 546 | |
520 | 547 | The following transformations are performed on the input: |
521 | 548 | |
551 | 578 | |
552 | 579 | =head2 require_module($module_name) |
553 | 580 | |
554 | This class method is used internally to take a module | |
555 | name (supplied by L<get_module_name>) and require it in a secure fashion. It | |
556 | is provided as a public class method so that if you override other functionality of | |
557 | this module, you can still safely require user specified modules. If there are | |
558 | any problems requiring the named module, then we will C<croak>. | |
581 | This class method is used internally to take a module name (supplied | |
582 | by L<get_module_name>) and require it in a secure fashion. It is | |
583 | provided as a public class method so that if you override other | |
584 | functionality of this module, you can still safely require user | |
585 | specified modules. If there are any problems requiring the named | |
586 | module, then we will C<croak>. | |
559 | 587 | |
560 | 588 | CGI::Application::Dispatch::PSGI->require_module('MyApp::Module::Name'); |
561 | 589 | |
621 | 649 | |
622 | 650 | Just so we all understand what we're talking about.... |
623 | 651 | |
624 | A table is an array where the elements are gouped as pairs (similar to a hash's | |
625 | key-value pairs, but as an array to preserve order). The first element of each pair | |
626 | is called a C<rule>. The second element in the pair is called the rule's C<arg list>. | |
627 | Inside a rule there are slashes C</>. Anything set of characters between slashes | |
628 | is called a C<token>. | |
652 | A table is an array where the elements are gouped as pairs (similar to | |
653 | a hash's key-value pairs, but as an array to preserve order). The | |
654 | first element of each pair is called a C<rule>. The second element in | |
655 | the pair is called the rule's C<arg list>. Inside a rule there are | |
656 | slashes C</>. Anything set of characters between slashes is called a | |
657 | C<token>. | |
629 | 658 | |
630 | 659 | =head2 URL MATCHING |
631 | 660 | |
632 | When a URL comes in, Dispatch tries to match it against each rule in the table in | |
633 | the order in which the rules are given. The first one to match wins. | |
661 | When a URL comes in, Dispatch tries to match it against each rule in | |
662 | the table in the order in which the rules are given. The first one to | |
663 | match wins. | |
634 | 664 | |
635 | 665 | A rule consists of slashes and tokens. A token can one of the following types: |
636 | 666 | |
647 | 677 | |
648 | 678 | =item variable |
649 | 679 | |
650 | Any token which begins with a colon (C<:>) is a variable token. These are simply | |
651 | wild-card place holders in the rule that will match anything in the URL that isn't | |
652 | a slash. These variables can later be referred to by using the C<< $self->param >> | |
653 | mechanism. In the rule | |
680 | Any token which begins with a colon (C<:>) is a variable token. These | |
681 | are simply wild-card place holders in the rule that will match | |
682 | anything in the URL that isn't a slash. These variables can later be | |
683 | referred to by using the C<< $self->param >> mechanism. In the rule | |
654 | 684 | |
655 | 685 | 'posts/:category' |
656 | 686 | |
657 | C<:category> is a variable token. If the URL matched this rule, then you could retrieve | |
658 | the value of that token from whithin your application like so: | |
687 | C<:category> is a variable token. If the URL matched this rule, then | |
688 | you could the value of that token from whithin your application like | |
689 | so: | |
659 | 690 | |
660 | 691 | my $category = $self->param('category'); |
661 | 692 | |
662 | There are some variable tokens which are special. These can be used to further customize | |
663 | the dispatching. | |
693 | There are some variable tokens which are special. These can be used to | |
694 | further customize the dispatching. | |
664 | 695 | |
665 | 696 | =over |
666 | 697 | |
667 | 698 | =item :app |
668 | 699 | |
669 | This is the module name of the application. The value of this token will be sent to the | |
670 | L<translate_module_name> method and then prefixed with the L<prefix> if there is one. | |
700 | This is the module name of the application. The value of this token | |
701 | will be sent to the L<translate_module_name> method and then prefixed | |
702 | with the L<prefix> if there is one. | |
671 | 703 | |
672 | 704 | =item :rm |
673 | 705 | |
674 | This is the run mode of the application. The value of this token will be the actual name | |
675 | of the run mode used. | |
706 | This is the run mode of the application. The value of this token will be the | |
707 | actual name of the run mode used. The run mode can be optional, as | |
708 | noted below. Example: | |
709 | ||
710 | /foo/:rm? | |
711 | ||
712 | If no run mode is found, it will default to using the C<< start_mode() >>, just like | |
713 | invoking CGI::Application directly. Both of these URLs would end up dispatching | |
714 | to the start mode associated with /foo: | |
715 | ||
716 | /foo/ | |
717 | /foo | |
676 | 718 | |
677 | 719 | =back |
678 | 720 | |
679 | 721 | =item optional-variable |
680 | 722 | |
681 | Any token which begins with a colon (C<:>) and ends with a question mark (<?>) is considered | |
682 | optional. If the rest of the URL matches the rest of the rule, then it doesn't matter whether | |
683 | it contains this token or not. It's best to only include optional-variable tokens at the end | |
684 | of your rule. In the rule | |
723 | Any token which begins with a colon (C<:>) and ends with a question | |
724 | mark (<?>) is considered optional. If the rest of the URL matches the | |
725 | rest of the rule, then it doesn't matter whether it contains this | |
726 | token or not. It's best to only include optional-variable tokens at | |
727 | the end of your rule. In the rule | |
685 | 728 | |
686 | 729 | 'date/:year/:month?/:day?' |
687 | 730 | |
688 | 731 | C<:month?> and C<:day?> are optional-variable tokens. |
689 | 732 | |
690 | Just like with L<variable> tokens, optional-variable tokens' values can also be retrieved by | |
691 | the application, if they existed in the URL. | |
733 | Just like with L<variable> tokens, optional-variable tokens' values | |
734 | can also be retrieved by the application, if they existed in the URL. | |
692 | 735 | |
693 | 736 | if( defined $self->param('month') ) { |
694 | 737 | ... |
696 | 739 | |
697 | 740 | =item wildcard |
698 | 741 | |
699 | The wildcard token "*" allows for partial matches. The token MUST appear at the end of the | |
700 | rule. | |
742 | The wildcard token "*" allows for partial matches. The token MUST | |
743 | appear at the end of the rule. | |
701 | 744 | |
702 | 745 | 'posts/list/*' |
703 | 746 | |
704 | By default, the C<dispatch_url_remainder> param is set to the remainder of the URL | |
705 | matched by the *. The name of the param can be changed by setting "*" argument in the | |
706 | L<ARG LIST>. | |
747 | By default, the C<dispatch_url_remainder> param is set to the | |
748 | remainder of the URL matched by the *. The name of the param can be | |
749 | changed by setting "*" argument in the L<ARG LIST>. | |
707 | 750 | |
708 | 751 | 'posts/list/*' => { '*' => 'post_list_filter' } |
709 | 752 | |
710 | 753 | =item method |
711 | 754 | |
712 | You can also dispatch based on HTTP method. This is similar to using L<auto_rest> but | |
713 | offers more fine grained control. You include the method (case insensitive) at the end of | |
714 | the rule and enclose it in square brackets. | |
755 | You can also dispatch based on HTTP method. This is similar to using | |
756 | L<auto_rest> but offers more fine grained control. You include the | |
757 | method (case insensitive) at the end of the rule and enclose it in | |
758 | square brackets. | |
715 | 759 | |
716 | 760 | ':app/news[post]' => { rm => 'add_news' }, |
717 | 761 | ':app/news[get]' => { rm => 'news' }, |
719 | 763 | |
720 | 764 | =back |
721 | 765 | |
722 | The main reason that we don't use regular expressions for dispatch rules is that regular | |
723 | expressions provide no mechanism for named back references, like variable tokens do. | |
766 | The main reason that we don't use regular expressions for dispatch | |
767 | rules is that regular expressions provide no mechanism for named back | |
768 | references, like variable tokens do. | |
724 | 769 | |
725 | 770 | =head2 ARG LIST |
726 | 771 | |
727 | Each rule can have an accompanying arg-list. This arg list can contain special arguments | |
728 | that override something set higher up in L<dispatch> for this particular URL, or just | |
729 | have additional args passed available in C<< $self->param() >> | |
730 | ||
731 | For instance, if you want to override L<prefix> for a specific rule, then you can do so. | |
772 | Each rule can have an accompanying arg-list. This arg list can contain | |
773 | special arguments that override something set higher up in L<dispatch> | |
774 | for this particular URL, or just have additional args passed available | |
775 | in C<< $self->param() >> | |
776 | ||
777 | For instance, if you want to override L<prefix> for a specific rule, | |
778 | then you can do so. | |
732 | 779 | |
733 | 780 | 'admin/:app/:rm' => { prefix => 'MyApp::Admin' }, |
734 | 781 | |
735 | 782 | =head1 Path Parsing |
736 | 783 | |
737 | This section will describe how the application module and run mode are determined from | |
738 | the path if no L<DISPATCH TABLE> is present, and what options you have to | |
739 | customize the process. The value for the path to be parsed is retrieved from | |
740 | C<< $env->{PATH_INFO} >>. | |
784 | This section will describe how the application module and run mode are | |
785 | determined from the path if no L<DISPATCH TABLE> is present, and what | |
786 | options you have to customize the process. The value for the path to | |
787 | be parsed is retrieved from C<< $env->{PATH_INFO} >>. | |
741 | 788 | |
742 | 789 | =head2 Getting the module name |
743 | 790 | |
744 | To get the name of the application module the path is split on backslahes (C</>). | |
745 | The second element of the returned list (the first is empty) is used to create the application module. So if we | |
746 | have a path of | |
791 | To get the name of the application module the path is split on | |
792 | backslahes (C</>). The second element of the returned list (the first | |
793 | is empty) is used to create the application module. So if we have a | |
794 | path of | |
747 | 795 | |
748 | 796 | /module_name/mode1 |
749 | 797 | |
750 | then the string 'module_name' is used. This is passed through the L<translate_module_name> | |
751 | method. Then if there is a C<prefix> (and there should always be a L<prefix>) it is added | |
752 | to the beginning of this new module name with a double colon C<::> separating the two. | |
753 | ||
754 | If you don't like the exact way that this is done, don't fret you do have a couple of options. | |
755 | First, you can specify a L<DISPATCH TABLE> which is much more powerful and flexible (in fact | |
756 | this default behavior is actually implemented internally with a dispatch table). | |
757 | Or if you want something a little simpler, you can simply subclass and extend the | |
758 | L<translate_module_name> method. | |
798 | then the string 'module_name' is used. This is passed through the | |
799 | L<translate_module_name> method. Then if there is a C<prefix> (and | |
800 | there should always be a L<prefix>) it is added to the beginning of | |
801 | this new module name with a double colon C<::> separating the two. | |
802 | ||
803 | If you don't like the exact way that this is done, don't fret you do | |
804 | have a couple of options. First, you can specify a L<DISPATCH TABLE> | |
805 | which is much more powerful and flexible (in fact this default | |
806 | behavior is actually implemented internally with a dispatch table). | |
807 | Or if you want something a little simpler, you can simply subclass and | |
808 | extend the L<translate_module_name> method. | |
759 | 809 | |
760 | 810 | =head2 Getting the run mode |
761 | 811 | |
762 | Just like the module name is retrieved from splitting the path on slashes, so is the | |
763 | run mode. Only instead of using the second element of the resulting list, we use the third | |
764 | as the run mode. So, using the same example, if we have a path of | |
812 | Just like the module name is retrieved from splitting the path on | |
813 | slashes, so is the run mode. Only instead of using the second element | |
814 | of the resulting list, we use the third as the run mode. So, using the | |
815 | same example, if we have a path of | |
765 | 816 | |
766 | 817 | /module_name/mode2 |
767 | 818 | |
768 | 819 | Then the string 'mode2' is used as the run mode. |
769 | 820 | |
821 | =head1 Exception Handling | |
822 | ||
823 | A CGI::Application object can throw an exception up to C<< | |
824 | CGI::Application::Dispatch::PSGI >> if no C<error_mode()> is implemented or if | |
825 | the error_mode itself throws an exception. In these cases we generally return a | |
826 | generic "500" response, and log some details for the developer with a warning. | |
827 | ||
828 | However, we will check to see if the exception thrown is an HTTP::Exception | |
829 | object. If that's the case, we will rethrow it, and you can handle it yourself using | |
830 | something like L<Plack::Middleware::HTTPExceptions>. | |
831 | ||
770 | 832 | =head1 MISC NOTES |
771 | 833 | |
772 | 834 | =over 8 |
773 | 835 | |
774 | 836 | =item * CGI query strings |
775 | 837 | |
776 | CGI query strings are unaffected by the use of C<PATH_INFO> to obtain the module name and run mode. | |
777 | This means that any other modules you use to get access to you query argument (ie, L<CGI>, | |
778 | L<Apache::Request>) should not be affected. But, since the run mode may be determined by | |
779 | CGI::Application::Dispatch::PSGI having a query argument named 'rm' will be ignored by your application | |
780 | module. | |
838 | CGI query strings are unaffected by the use of C<PATH_INFO> to obtain | |
839 | the module name and run mode. This means that any other modules you | |
840 | use to get access to you query argument (ie, L<CGI>, | |
841 | L<Apache::Request>) should not be affected. But, since the run mode | |
842 | may be determined by CGI::Application::Dispatch::PSGI having a query | |
843 | argument named 'rm' will be ignored by your application module. | |
781 | 844 | |
782 | 845 | =back |
783 | 846 | |
787 | 850 | |
788 | 851 | /cgi-bin/dispatch.cgi/module_name/run_mode |
789 | 852 | |
790 | However, including "/cgi-bin/dispatch.cgi" in ever URL doesn't add any value to the URL, | |
791 | so it's nice to remove it. This is easily done if you are using the Apache web server with | |
792 | C<mod_rewrite> available. Adding the following to a C<.htaccess> file would allow you to | |
793 | simply use: | |
853 | However, including "/cgi-bin/dispatch.cgi" in ever URL doesn't add any | |
854 | value to the URL, so it's nice to remove it. This is easily done if | |
855 | you are using the Apache web server with C<mod_rewrite> | |
856 | available. Adding the following to a C<.htaccess> file would allow you | |
857 | to simply use: | |
794 | 858 | |
795 | 859 | /module_name/run_mode |
796 | 860 | |
797 | If you have problems with mod_rewrite, turn on debugging to see exactly what's happening: | |
861 | If you have problems with mod_rewrite, turn on debugging to see | |
862 | exactly what's happening: | |
798 | 863 | |
799 | 864 | RewriteLog /home/project/logs/alpha-rewrite.log |
800 | 865 | RewriteLogLevel 9 |
829 | 894 | be treated as a directory, and also supports multiple developer directories, |
830 | 895 | so C</~mark> has its own separate dispatching system beneath it. |
831 | 896 | |
832 | Note that order matters here! The Location block for "/" needs to come before the | |
833 | user blocks. | |
897 | Note that order matters here! The Location block for "/" needs to come | |
898 | before the user blocks. | |
834 | 899 | |
835 | 900 | <Location /> |
836 | 901 | RewriteEngine On |
855 | 920 | # Run "/" through the dispatcher |
856 | 921 | RewriteRule ^/home/mark/www/$ /~mark/cgi-bin/dispatch.cgi [L,QSA] |
857 | 922 | |
858 | # Otherwise, if an actual file or directory is requested, serve directly | |
923 | # Otherwise, if an actual file or directory is requested, serve directly | |
859 | 924 | RewriteCond %{REQUEST_FILENAME} !-f |
860 | 925 | RewriteCond %{REQUEST_FILENAME} !-d |
861 | 926 | |
862 | # Otherwise, pass everything through to the dispatcher | |
927 | # Otherwise, pass everything through to the dispatcher | |
863 | 928 | RewriteRule ^(.*)$ /~mark/cgi-bin/dispatch.cgi/$1 [L,QSA] |
864 | 929 | |
865 | 930 | # These examples may also be helpful, but are unrelated to dispatching. |
871 | 936 | |
872 | 937 | =head1 SUBCLASSING |
873 | 938 | |
874 | While Dispatch tries to be flexible, it won't be able to do everything that people want. Hopefully | |
875 | we've made it flexible enough so that if it doesn't do I<The Right Thing> you can easily subclass | |
876 | it. | |
939 | While Dispatch tries to be flexible, it won't be able to do everything | |
940 | that people want. Hopefully we've made it flexible enough so that if | |
941 | it doesn't do I<The Right Thing> you can easily subclass it. | |
877 | 942 | |
878 | 943 | =cut |
879 | 944 | |
880 | 945 | #=head2 PROTECTED METHODS |
881 | 946 | # |
882 | #The following methods are intended to be overridden by subclasses if necessary. They are not | |
883 | #part of the public API since end users will never touch them. However, to ensure that your | |
884 | #subclass of Dispatch does not break with a new release, they are documented here and are considered | |
885 | #to be part of the API and will not be changed without very good reasons. | |
947 | #The following methods are intended to be overridden by subclasses if | |
948 | #necessary. They are not part of the public API since end users will | |
949 | #never touch them. However, to ensure that your subclass of Dispatch | |
950 | #does not break with a new release, they are documented here and are | |
951 | #considered to be part of the API and will not be changed without very | |
952 | #good reasons. | |
886 | 953 | |
887 | 954 | =head1 AUTHORS |
888 | 955 | |
889 | 956 | Mark Stosberg <mark@summersault.com> |
890 | 957 | |
891 | Heavily based on CGI::Application::Dispatch, written by Michael Peters <mpeters@plusthree.com> and others | |
958 | Heavily based on CGI::Application::Dispatch, written by Michael Peters | |
959 | <mpeters@plusthree.com> and others | |
892 | 960 | |
893 | 961 | =head1 COMMUNITY |
894 | 962 | |
895 | This module is a part of the larger L<CGI::Application> community. If you have questions or | |
896 | comments about this module then please join us on the cgiapp mailing list by sending a blank | |
897 | message to "cgiapp-subscribe@lists.erlbaum.net". There is also a community wiki located at | |
898 | L<http://www.cgi-app.org/> | |
963 | This module is a part of the larger L<CGI::Application> community. If | |
964 | you have questions or comments about this module then please join us | |
965 | on the cgiapp mailing list by sending a blank message to | |
966 | "cgiapp-subscribe@lists.erlbaum.net". There is also a community wiki | |
967 | located at L<http://www.cgi-app.org/> | |
899 | 968 | |
900 | 969 | =head1 SOURCE CODE REPOSITORY |
901 | 970 | |
950 | 1019 | |
951 | 1020 | =item dispatch_path() |
952 | 1021 | |
953 | The dispatch_path() method is not supported. The alternative is to reference C<< $env->{PATH_INFO} >> which is | |
954 | available per the PSGI spec. | |
1022 | The dispatch_path() method is not supported. The alternative is to | |
1023 | reference C<< $env->{PATH_INFO} >> which is available per the PSGI | |
1024 | spec. | |
955 | 1025 | |
956 | 1026 | =item handler() |
957 | 1027 | |
958 | This provided an Apache-specific handler. Other PSGI components like L<Plack::Handler::Apache2> provide | |
959 | Apache handlers now instead. | |
1028 | This provided an Apache-specific handler. Other PSGI components like | |
1029 | L<Plack::Handler::Apache2> provide Apache handlers now instead. | |
960 | 1030 | |
961 | 1031 | =item _http_method() |
962 | 1032 | |
963 | This method has been eliminated. Check C<< $env->{REQUEST_METHOD} >> directly instead. | |
1033 | This method has been eliminated. Check C<< $env->{REQUEST_METHOD} >> | |
1034 | directly instead. | |
964 | 1035 | |
965 | 1036 | =item _parse_path() |
966 | 1037 | |
967 | The private _parse_path() method now accepts an additional argument, the PSGI C<< $env >> hash. | |
1038 | The private _parse_path() method now accepts an additional argument, | |
1039 | the PSGI C<< $env >> hash. | |
968 | 1040 | |
969 | 1041 | =item _run_app() |
970 | 1042 | |
971 | The private _run_app() method now accepts an additional argument, the PSGI C<< $env >> hash. | |
1043 | The private _run_app() method now accepts an additional argument, the | |
1044 | PSGI C<< $env >> hash. | |
972 | 1045 | |
973 | 1046 | =item _r() |
974 | 1047 |
7 | 7 | |
8 | 8 | =head1 NAME |
9 | 9 | |
10 | CGI::Application::Dispatch::Regexp - Dispatch requests to CGI::Application based objects using regular expressions | |
10 | CGI::Application::Dispatch::Regexp - Dispatch requests to | |
11 | CGI::Application based objects using regular expressions | |
11 | 12 | |
12 | 13 | =head1 SYNOPSIS |
13 | 14 | |
14 | 15 | use CGI::Application::Dispatch::Regexp; |
15 | 16 | |
16 | 17 | CGI::Application::Dispatch::Regexp->dispatch( |
17 | prefix => 'MyApp', | |
18 | table => [ | |
19 | '' => { app => 'Welcome', rm => 'start' }, | |
20 | qr|/([^/]+)/?| => { names => ['app'] }, | |
21 | qr|/([^/]+)/([^/]+)/?| => { names => [qw(app rm)] }, | |
22 | qr|/([^/]+)/([^/]+)/page(\d+)\.html?| => { names => [qw(app rm page)] }, | |
23 | ], | |
18 | prefix => 'MyApp', | |
19 | table => [ | |
20 | '' => { app => 'Welcome', | |
21 | rm => 'start', | |
22 | }, | |
23 | qr|/([^/]+)/?| => { names => ['app'], | |
24 | }, | |
25 | qr|/([^/]+)/([^/]+)/?| => { names => | |
26 | [qw(app rm)] | |
27 | }, | |
28 | qr|/([^/]+)/([^/]+)/page(\d+)\.html?| => { names => | |
29 | [qw(app rm page)] | |
30 | }, | |
31 | ], | |
24 | 32 | ); |
25 | 33 | |
26 | 34 | |
27 | 35 | =head1 DESCRIPTION |
28 | 36 | |
29 | 37 | L<CGI::Application::Dispatch> uses its own syntax dispatch table. |
30 | C<CGI::Application::Dispatch::Regexp> allows one to use flexible and powerful Perl | |
31 | regular expressions to transform a path into argument list. | |
38 | C<CGI::Application::Dispatch::Regexp> allows one to use flexible and | |
39 | powerful Perl regular expressions to transform a path into argument | |
40 | list. | |
32 | 41 | |
33 | 42 | =head1 DISPATCH TABLE |
34 | 43 | |
43 | 52 | |
44 | 53 | Here's an example of defining a custom 'page' parameter: |
45 | 54 | |
46 | qr|/([^/]+)/([^/]+)/page(\d+)\.html/?| => { names => [qw(app rm page)] }, | |
55 | qr|/([^/]+)/([^/]+)/page(\d+)\.html/?| => { | |
56 | names => [qw(app rm page)], | |
57 | }, | |
47 | 58 | |
48 | 59 | |
49 | 60 | =head1 COPYRIGHT & LICENSE |
71 | 82 | |
72 | 83 | for(my $i = 0 ; $i < scalar(@$table) ; $i += 2) { |
73 | 84 | |
74 | # translate the rule into a regular expression, but remember where the named args are | |
85 | # translate the rule into a regular expression, but remember | |
86 | # where the named args are | |
75 | 87 | my $rule = $table->[$i]; |
76 | 88 | |
77 | 89 | warn |
0 | 0 | package CGI::Application::Dispatch; |
1 | 1 | use strict; |
2 | 2 | use warnings; |
3 | use Carp qw(carp cluck); | |
3 | use Carp 'carp'; | |
4 | 4 | use Try::Tiny; |
5 | 5 | |
6 | our $VERSION = '3.07'; | |
6 | our $VERSION = '3.12'; | |
7 | 7 | our $DEBUG = 0; |
8 | 8 | |
9 | 9 | BEGIN { |
107 | 107 | |
108 | 108 | =head1 DESCRIPTION |
109 | 109 | |
110 | This module provides a way (as a mod_perl handler or running under vanilla CGI) to look at | |
111 | the path (as returned by L<dispatch_path>) of the incoming request, parse | |
112 | off the desired module and its run mode, create an instance of that module and run it. | |
113 | ||
114 | It currently supports both generations of mod_perl (1.x and 2.x). Although, for simplicity, | |
115 | all examples involving Apache configuration and mod_perl code will be shown using mod_perl 1.x. | |
110 | This module provides a way (as a mod_perl handler or running under | |
111 | vanilla CGI) to look at the path (as returned by L<dispatch_path>) of | |
112 | the incoming request, parse off the desired module and its run mode, | |
113 | create an instance of that module and run it. | |
114 | ||
115 | It currently supports both generations of mod_perl (1.x and | |
116 | 2.x). Although, for simplicity, all examples involving Apache | |
117 | configuration and mod_perl code will be shown using mod_perl 1.x. | |
116 | 118 | This may change as mp2 usage increases. |
117 | 119 | |
118 | 120 | It will translate a URI like this (under mod_perl): |
132 | 134 | |
133 | 135 | =head2 dispatch(%args) |
134 | 136 | |
135 | This is the primary method used during dispatch. Even under mod_perl, the L<handler> | |
136 | method uses this under the hood. | |
137 | This is the primary method used during dispatch. Even under mod_perl, | |
138 | the L<handler> method uses this under the hood. | |
137 | 139 | |
138 | 140 | #!/usr/bin/perl |
139 | 141 | use strict; |
155 | 157 | |
156 | 158 | =item prefix |
157 | 159 | |
158 | This option will set the string that will be prepended to the name of the application | |
159 | module before it is loaded and created. So to use our previous example request of | |
160 | This option will set the string that will be prepended to the name of | |
161 | the application module before it is loaded and created. So to use our | |
162 | previous example request of | |
160 | 163 | |
161 | 164 | /app/index.cgi/module_name/run_mode |
162 | 165 | |
163 | This would by default load and create a module named 'Module::Name'. But let's say that you | |
164 | have all of your application specific modules under the 'My' namespace. If you set this option | |
165 | to 'My' then it would instead load the 'My::Module::Name' application module instead. | |
166 | This would by default load and create a module named | |
167 | 'Module::Name'. But let's say that you have all of your application | |
168 | specific modules under the 'My' namespace. If you set this option to | |
169 | 'My' then it would instead load the 'My::Module::Name' application | |
170 | module instead. | |
166 | 171 | |
167 | 172 | =item args_to_new |
168 | 173 | |
169 | This is a hash of arguments that are passed into the C<new()> constructor of the application. | |
174 | This is a hash of arguments that are passed into the C<new()> | |
175 | constructor of the application. | |
170 | 176 | |
171 | 177 | =item table |
172 | 178 | |
173 | In most cases, simply using Dispatch with the C<default> and C<prefix> is enough | |
174 | to simplify your application and your URLs, but there are many cases where you want | |
175 | more power. Enter the dispatch table. Since this table can be slightly complicated, | |
176 | a whole section exists on its use. Please see the L<DISPATCH TABLE> section. | |
179 | In most cases, simply using Dispatch with the C<default> and C<prefix> | |
180 | is enough to simplify your application and your URLs, but there are | |
181 | many cases where you want more power. Enter the dispatch table. Since | |
182 | this table can be slightly complicated, a whole section exists on its | |
183 | use. Please see the L<DISPATCH TABLE> section. | |
177 | 184 | |
178 | 185 | =item debug |
179 | 186 | |
180 | Set to a true value to send debugging output for this module to STDERR. Off by default. | |
187 | Set to a true value to send debugging output for this module to | |
188 | STDERR. Off by default. | |
181 | 189 | |
182 | 190 | =item error_document |
183 | 191 | |
192 | 200 | character will be trimmed from final output. |
193 | 201 | |
194 | 202 | B<A file with content of error document> |
195 | - if it starts with greater-than sign (C<<>). First character will be excluded | |
203 | - if it starts with less-than sign (C<<>). First character will be excluded | |
196 | 204 | as well. Path of this file should be relative to server DOCUMENT_ROOT. |
197 | 205 | |
198 | 206 | B<A URI to which the application will be redirected> - if no leading C<"> or |
226 | 234 | # internal redirect to /errors/error404.html |
227 | 235 | error_document => '/errors/error%s.html' |
228 | 236 | |
229 | # external redirect to http://host.domain/cgi-bin/errors.cgi?error=404 | |
237 | # external redirect to | |
238 | # http://host.domain/cgi-bin/errors.cgi?error=404 | |
230 | 239 | error_document => 'http://host.domain/cgi-bin/errors.cgi?error=%s' |
231 | 240 | |
232 | 241 | =item auto_rest |
233 | 242 | |
234 | This tells Dispatch that you are using REST by default and that you care about which HTTP method | |
235 | is being used. Dispatch will append the HTTP method name (upper case by default) to | |
236 | the run mode that is determined after finding the appropriate dispatch rule. So a GET request | |
237 | that translates into C<MyApp::Module->foo> will become C<MyApp::Module->foo_GET>. | |
243 | This tells Dispatch that you are using REST by default and that you | |
244 | care about which HTTP method is being used. Dispatch will append the | |
245 | HTTP method name (upper case by default) to the run mode that is | |
246 | determined after finding the appropriate dispatch rule. So a GET | |
247 | request that translates into C<< MyApp::Module->foo >> will become | |
248 | C<< MyApp::Module->foo_GET >>. | |
238 | 249 | |
239 | 250 | This can be overridden on a per-rule basis in a custom dispatch table. |
240 | 251 | |
241 | 252 | =item auto_rest_lc |
242 | 253 | |
243 | In combinaion with L<auto_rest> this tells Dispatch that you prefer lower cased HTTP method names. | |
244 | So instead of C<foo_POST> and C<foo_GET> you'll have C<foo_post> and C<foo_get>. | |
254 | In combinaion with L<auto_rest> this tells Dispatch that you prefer | |
255 | lower cased HTTP method names. So instead of C<foo_POST> and | |
256 | C<foo_GET> you'll have C<foo_post> and C<foo_get>. | |
245 | 257 | |
246 | 258 | =back |
247 | 259 | |
329 | 341 | unless exists($args{error_document}); |
330 | 342 | } |
331 | 343 | |
332 | %args = map { lc $_ => $args{$_} } keys %args; # lc for backwards compatability | |
344 | %args = map { lc $_ => $args{$_} } keys %args; # lc for backwards | |
345 | # compatability | |
333 | 346 | |
334 | 347 | # get the PATH_INFO |
335 | 348 | my $path_info = $self->dispatch_path(); |
337 | 350 | # use the 'default' if we need to |
338 | 351 | $path_info = $args{default} || '' if(!$path_info || $path_info eq '/'); |
339 | 352 | |
340 | # make sure they all start and end with a '/', to correspond with the RE we'll make | |
353 | # make sure they all start and end with a '/', to correspond with | |
354 | # the RE we'll make | |
341 | 355 | $path_info = "/$path_info" unless(index($path_info, '/') == 0); |
342 | 356 | $path_info = "$path_info/" unless(substr($path_info, -1) eq '/'); |
343 | 357 | |
389 | 403 | |
390 | 404 | my $auto_rest = |
391 | 405 | defined $named_args->{auto_rest} ? $named_args->{auto_rest} : $args{auto_rest}; |
392 | if($auto_rest) { | |
406 | if($auto_rest && defined $rm && length $rm) { | |
393 | 407 | my $method_lc = |
394 | 408 | defined $named_args->{auto_rest_lc} |
395 | 409 | ? $named_args->{auto_rest_lc} |
404 | 418 | $output = $self->_run_app($module, $rm, $local_args_to_new); |
405 | 419 | } catch { |
406 | 420 | my $e = $_; |
407 | unless ( ref $e ) { | |
408 | local $@ = $e; | |
409 | $e = Exception::Class->caught(); | |
421 | unless ( ref $e && $e->isa('Exception::Class::Base') ) { | |
422 | $e = Exception::Class::Base->new($e); | |
410 | 423 | } |
411 | 424 | $output = $self->http_error($e, $args{error_document}); |
412 | 425 | }; |
557 | 570 | |
558 | 571 | unless($output) { |
559 | 572 | |
560 | # TODO: possibly provide more feedback in a way that is XSS safe. | |
561 | # (I'm not sure that passing through the raw ENV variable directly is safe.) | |
573 | # TODO: possibly provide more feedback in a way that | |
574 | # is XSS safe. (I'm not sure that passing through the | |
575 | # raw ENV variable directly is safe.) | |
562 | 576 | # <P>We tried: $ENV{REQUEST_URI}</P></BODY></HTML>"; |
563 | 577 | $output = qq( |
564 | 578 | <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> |
629 | 643 | $rule =~ s/$http_method_regex//; |
630 | 644 | } |
631 | 645 | |
632 | # make sure they start and end with a '/' to match how PATH_INFO is formatted | |
646 | # make sure they start and end with a '/' to match how | |
647 | # PATH_INFO is formatted | |
633 | 648 | $rule = "/$rule" unless(index($rule, '/') == 0); |
634 | 649 | $rule = "$rule/" if(substr($rule, -1) ne '/'); |
635 | 650 | |
636 | 651 | my @names = (); |
637 | 652 | |
638 | # translate the rule into a regular expression, but remember where the named args are | |
653 | # translate the rule into a regular expression, but remember | |
654 | # where the named args are | |
639 | 655 | # '/:foo' will become '/([^\/]*)' |
640 | 656 | # and |
641 | 657 | # '/:bar?' will become '/?([^\/]*)?' |
734 | 750 | PerlSetVar CGIAPP_DISPATCH_DEFAULT /module_name |
735 | 751 | </Location> |
736 | 752 | |
737 | The above example would tell apache that any url beginning with /app will be handled by | |
738 | CGI::Application::Dispatch. It also sets the prefix used to create the application module | |
739 | to 'MyApp' and it tells CGI::Application::Dispatch that it shouldn't set the run mode | |
740 | but that it will be determined by the application module as usual (through the query | |
741 | string). It also sets a default application module to be used if there is no path. | |
742 | So, a url of C</app/module_name> would create an instance of C<MyApp::Module::Name>. | |
743 | ||
744 | Using this method will add the C<Apache->request> object to your application's C<PARAMS> | |
745 | as 'r'. | |
753 | The above example would tell apache that any url beginning with /app | |
754 | will be handled by CGI::Application::Dispatch. It also sets the prefix | |
755 | used to create the application module to 'MyApp' and it tells | |
756 | CGI::Application::Dispatch that it shouldn't set the run mode but that | |
757 | it will be determined by the application module as usual (through the | |
758 | query string). It also sets a default application module to be used if | |
759 | there is no path. So, a url of C</app/module_name> would create an | |
760 | instance of C<MyApp::Module::Name>. | |
761 | ||
762 | Using this method will add the C<Apache->request> object to your | |
763 | application's C<PARAMS> as 'r'. | |
746 | 764 | |
747 | 765 | # inside your app |
748 | 766 | my $request = $self->param('r'); |
749 | 767 | |
750 | If you need more customization than can be accomplished with just L<prefix> | |
751 | and L<default>, then it would be best to just subclass CGI::Application::Dispatch | |
752 | and override L<dispatch_args> since C<handler()> uses L<dispatch> to do the heavy lifting. | |
768 | If you need more customization than can be accomplished with just | |
769 | L<prefix> and L<default>, then it would be best to just subclass | |
770 | CGI::Application::Dispatch and override L<dispatch_args> since | |
771 | C<handler()> uses L<dispatch> to do the heavy lifting. | |
753 | 772 | |
754 | 773 | package MyApp::Dispatch; |
755 | 774 | use base 'CGI::Application::Dispatch'; |
791 | 810 | # setup our args to dispatch() |
792 | 811 | my %args; |
793 | 812 | my $config_args = $r->dir_config(); |
794 | for my $var qw(DEFAULT PREFIX ERROR_DOCUMENT) { | |
813 | for my $var (qw(DEFAULT PREFIX ERROR_DOCUMENT)) { | |
795 | 814 | my $dir_var = "CGIAPP_DISPATCH_$var"; |
796 | 815 | $args{lc($var)} = $config_args->{$dir_var} |
797 | 816 | if($config_args->{$dir_var}); |
823 | 842 | |
824 | 843 | =head2 dispatch_args() |
825 | 844 | |
826 | Returns a hashref of args that will be passed to L<dispatch>(). It will return the following | |
827 | structure by default. | |
845 | Returns a hashref of args that will be passed to L<dispatch>(). It | |
846 | will return the following structure by default. | |
828 | 847 | |
829 | 848 | { |
830 | 849 | prefix => '', |
835 | 854 | ], |
836 | 855 | } |
837 | 856 | |
838 | This is the perfect place to override when creating a subclass to provide a richer dispatch | |
839 | L<table>. | |
840 | ||
841 | When called, it receives 1 argument, which is a reference to the hash of args passed into | |
842 | L<dispatch>. | |
857 | This is the perfect place to override when creating a subclass to | |
858 | provide a richer dispatch L<table>. | |
859 | ||
860 | When called, it receives 1 argument, which is a reference to the hash | |
861 | of args passed into L<dispatch>. | |
843 | 862 | |
844 | 863 | =cut |
845 | 864 | |
859 | 878 | =head2 translate_module_name($input) |
860 | 879 | |
861 | 880 | This method is used to control how the module name is translated from |
862 | the matching section of the path (see L<"Path Parsing">. | |
863 | The main reason that this method exists is so that it can be overridden if it doesn't do | |
864 | exactly what you want. | |
881 | the matching section of the path (see L<"Path Parsing">). | |
882 | The main | |
883 | reason that this method exists is so that it can be overridden if it | |
884 | doesn't do exactly what you want. | |
865 | 885 | |
866 | 886 | The following transformations are performed on the input: |
867 | 887 | |
897 | 917 | |
898 | 918 | =head2 require_module($module_name) |
899 | 919 | |
900 | This class method is used internally by CGI::Application::Dispatch to take a module | |
901 | name (supplied by L<get_module_name>) and require it in a secure fashion. It | |
902 | is provided as a public class method so that if you override other functionality of | |
903 | this module, you can still safely require user specified modules. If there are | |
904 | any problems requiring the named module, then we will C<croak>. | |
920 | This class method is used internally by CGI::Application::Dispatch to | |
921 | take a module name (supplied by L<get_module_name>) and require it in | |
922 | a secure fashion. It is provided as a public class method so that if | |
923 | you override other functionality of this module, you can still safely | |
924 | require user specified modules. If there are any problems requiring | |
925 | the named module, then we will C<croak>. | |
905 | 926 | |
906 | 927 | CGI::Application::Dispatch->require_module('MyApp::Module::Name'); |
907 | 928 | |
958 | 979 | ] |
959 | 980 | ); |
960 | 981 | |
961 | So first, this call to L<dispatch> sets the L<prefix> and passes a C<TMPL_PATH> | |
962 | into L<args_to_new>. Next it sets the L<table>. | |
982 | So first, this call to L<dispatch> sets the L<prefix> and passes a | |
983 | C<TMPL_PATH> into L<args_to_new>. Next it sets the L<table>. | |
963 | 984 | |
964 | 985 | |
965 | 986 | =head2 VOCABULARY |
966 | 987 | |
967 | 988 | Just so we all understand what we're talking about.... |
968 | 989 | |
969 | A table is an array where the elements are gouped as pairs (similar to a hash's | |
970 | key-value pairs, but as an array to preserve order). The first element of each pair | |
971 | is called a C<rule>. The second element in the pair is called the rule's C<arg list>. | |
972 | Inside a rule there are slashes C</>. Anything set of characters between slashes | |
973 | is called a C<token>. | |
990 | A table is an array where the elements are gouped as pairs (similar to | |
991 | a hash's key-value pairs, but as an array to preserve order). The | |
992 | first element of each pair is called a C<rule>. The second element in | |
993 | the pair is called the rule's C<arg list>. Inside a rule there are | |
994 | slashes C</>. Anything set of characters between slashes is called a | |
995 | C<token>. | |
974 | 996 | |
975 | 997 | =head2 URL MATCHING |
976 | 998 | |
977 | When a URL comes in, Dispatch tries to match it against each rule in the table in | |
978 | the order in which the rules are given. The first one to match wins. | |
999 | When a URL comes in, Dispatch tries to match it against each rule in | |
1000 | the table in the order in which the rules are given. The first one to | |
1001 | match wins. | |
979 | 1002 | |
980 | 1003 | A rule consists of slashes and tokens. A token can one of the following types: |
981 | 1004 | |
992 | 1015 | |
993 | 1016 | =item variable |
994 | 1017 | |
995 | Any token which begins with a colon (C<:>) is a variable token. These are simply | |
996 | wild-card place holders in the rule that will match anything in the URL that isn't | |
997 | a slash. These variables can later be referred to by using the C<< $self->param >> | |
998 | mechanism. In the rule | |
1018 | Any token which begins with a colon (C<:>) is a variable token. These | |
1019 | are simply wild-card place holders in the rule that will match | |
1020 | anything in the URL that isn't a slash. These variables can later be | |
1021 | referred to by using the C<< $self->param >> mechanism. In the rule | |
999 | 1022 | |
1000 | 1023 | 'posts/:category' |
1001 | 1024 | |
1002 | C<:category> is a variable token. If the URL matched this rule, then you could retrieve | |
1003 | the value of that token from whithin your application like so: | |
1025 | C<:category> is a variable token. If the URL matched this rule, then | |
1026 | you could retrieve the value of that token from whithin your | |
1027 | application like so: | |
1004 | 1028 | |
1005 | 1029 | my $category = $self->param('category'); |
1006 | 1030 | |
1007 | There are some variable tokens which are special. These can be used to further customize | |
1008 | the dispatching. | |
1031 | There are some variable tokens which are special. These can be used to | |
1032 | further customize the dispatching. | |
1009 | 1033 | |
1010 | 1034 | =over |
1011 | 1035 | |
1012 | 1036 | =item :app |
1013 | 1037 | |
1014 | This is the module name of the application. The value of this token will be sent to the | |
1015 | L<translate_module_name> method and then prefixed with the L<prefix> if there is one. | |
1038 | This is the module name of the application. The value of this token | |
1039 | will be sent to the L<translate_module_name> method and then prefixed | |
1040 | with the L<prefix> if there is one. | |
1016 | 1041 | |
1017 | 1042 | =item :rm |
1018 | 1043 | |
1019 | This is the run mode of the application. The value of this token will be the actual name | |
1020 | of the run mode used. | |
1044 | This is the run mode of the application. The value of this token will be the | |
1045 | actual name of the run mode used. The run mode can be optional, as | |
1046 | noted below. Example: | |
1047 | ||
1048 | /foo/:rm? | |
1049 | ||
1050 | If no run mode is found, it will default to using the C<< start_mode() >>, just like | |
1051 | invoking CGI::Application directly. Both of these URLs would end up dispatching | |
1052 | to the start mode associated with /foo: | |
1053 | ||
1054 | /foo/ | |
1055 | /foo | |
1021 | 1056 | |
1022 | 1057 | =back |
1023 | 1058 | |
1024 | 1059 | =item optional-variable |
1025 | 1060 | |
1026 | Any token which begins with a colon (C<:>) and ends with a question mark (<?>) is considered | |
1027 | optional. If the rest of the URL matches the rest of the rule, then it doesn't matter whether | |
1028 | it contains this token or not. It's best to only include optional-variable tokens at the end | |
1029 | of your rule. In the rule | |
1061 | Any token which begins with a colon (C<:>) and ends with a question | |
1062 | mark (<?>) is considered optional. If the rest of the URL matches the | |
1063 | rest of the rule, then it doesn't matter whether it contains this | |
1064 | token or not. It's best to only include optional-variable tokens at | |
1065 | the end of your rule. In the rule | |
1030 | 1066 | |
1031 | 1067 | 'date/:year/:month?/:day?' |
1032 | 1068 | |
1033 | 1069 | C<:month?> and C<:day?> are optional-variable tokens. |
1034 | 1070 | |
1035 | Just like with L<variable> tokens, optional-variable tokens' values can also be retrieved by | |
1036 | the application, if they existed in the URL. | |
1071 | Just like with L<variable> tokens, optional-variable tokens' values | |
1072 | can also be retrieved by the application, if they existed in the URL. | |
1037 | 1073 | |
1038 | 1074 | if( defined $self->param('month') ) { |
1039 | 1075 | ... |
1041 | 1077 | |
1042 | 1078 | =item wildcard |
1043 | 1079 | |
1044 | The wildcard token "*" allows for partial matches. The token MUST appear at the end of the | |
1045 | rule. | |
1080 | The wildcard token "*" allows for partial matches. The token MUST | |
1081 | appear at the end of the rule. | |
1046 | 1082 | |
1047 | 1083 | 'posts/list/*' |
1048 | 1084 | |
1049 | By default, the C<dispatch_url_remainder> param is set to the remainder of the URL | |
1050 | matched by the *. The name of the param can be changed by setting "*" argument in the | |
1051 | L<ARG LIST>. | |
1085 | By default, the C<dispatch_url_remainder> param is set to the | |
1086 | remainder of the URL matched by the *. The name of the param can be | |
1087 | changed by setting "*" argument in the L<ARG LIST>. | |
1052 | 1088 | |
1053 | 1089 | 'posts/list/*' => { '*' => 'post_list_filter' } |
1054 | 1090 | |
1055 | 1091 | =item method |
1056 | 1092 | |
1057 | You can also dispatch based on HTTP method. This is similar to using L<auto_rest> but | |
1058 | offers more fine grained control. You include the method (case insensitive) at the end of | |
1059 | the rule and enclose it in square brackets. | |
1093 | You can also dispatch based on HTTP method. This is similar to using | |
1094 | L<auto_rest> but offers more fine grained control. You include the | |
1095 | method (case insensitive) at the end of the rule and enclose it in | |
1096 | square brackets. | |
1060 | 1097 | |
1061 | 1098 | ':app/news[post]' => { rm => 'add_news' }, |
1062 | 1099 | ':app/news[get]' => { rm => 'news' }, |
1064 | 1101 | |
1065 | 1102 | =back |
1066 | 1103 | |
1067 | The main reason that we don't use regular expressions for dispatch rules is that regular | |
1068 | expressions provide no mechanism for named back references, like variable tokens do. | |
1104 | The main reason that we don't use regular expressions for dispatch | |
1105 | rules is that regular expressions provide no mechanism for named back | |
1106 | references, like variable tokens do. | |
1069 | 1107 | |
1070 | 1108 | =head2 ARG LIST |
1071 | 1109 | |
1072 | Each rule can have an accompanying arg-list. This arg list can contain special arguments | |
1073 | that override something set higher up in L<dispatch> for this particular URL, or just | |
1074 | have additional args passed available in C<< $self->param() >> | |
1075 | ||
1076 | For instance, if you want to override L<prefix> for a specific rule, then you can do so. | |
1110 | Each rule can have an accompanying arg-list. This arg list can contain | |
1111 | special arguments that override something set higher up in L<dispatch> | |
1112 | for this particular URL, or just have additional args passed available | |
1113 | in C<< $self->param() >> | |
1114 | ||
1115 | For instance, if you want to override L<prefix> for a specific rule, | |
1116 | then you can do so. | |
1077 | 1117 | |
1078 | 1118 | 'admin/:app/:rm' => { prefix => 'MyApp::Admin' }, |
1079 | 1119 | |
1080 | 1120 | =head1 Path Parsing |
1081 | 1121 | |
1082 | This section will describe how the application module and run mode are determined from | |
1083 | the path if no L<DISPATCH TABLE> is present, and what options you have to | |
1084 | customize the process. The value for the path to be parsed is retrieved from | |
1085 | the L<dispatch_path> method, which by default uses the C<PATH_INFO> environment | |
1086 | variable. | |
1122 | This section will describe how the application module and run mode are | |
1123 | determined from the path if no L<DISPATCH TABLE> is present, and what | |
1124 | options you have to customize the process. The value for the path to | |
1125 | be parsed is retrieved from the L<dispatch_path> method, which by | |
1126 | default uses the C<PATH_INFO> environment variable. | |
1087 | 1127 | |
1088 | 1128 | =head2 Getting the module name |
1089 | 1129 | |
1090 | To get the name of the application module the path is split on backslahes (C</>). | |
1091 | The second element of the returned list (the first is empty) is used to create the application module. So if we | |
1092 | have a path of | |
1130 | To get the name of the application module the path is split on | |
1131 | backslahes (C</>). The second element of the returned list (the first | |
1132 | is empty) is used to create the application module. So if we have a | |
1133 | path of | |
1093 | 1134 | |
1094 | 1135 | /module_name/mode1 |
1095 | 1136 | |
1096 | then the string 'module_name' is used. This is passed through the L<translate_module_name> | |
1097 | method. Then if there is a C<prefix> (and there should always be a L<prefix>) it is added | |
1098 | to the beginning of this new module name with a double colon C<::> separating the two. | |
1099 | ||
1100 | If you don't like the exact way that this is done, don't fret you do have a couple of options. | |
1101 | First, you can specify a L<DISPATCH TABLE> which is much more powerful and flexible (in fact | |
1102 | this default behavior is actually implemented internally with a dispatch table). | |
1103 | Or if you want something a little simpler, you can simply subclass and extend the | |
1104 | L<translate_module_name> method. | |
1137 | then the string 'module_name' is used. This is passed through the | |
1138 | L<translate_module_name> method. Then if there is a C<prefix> (and | |
1139 | there should always be a L<prefix>) it is added to the beginning of | |
1140 | this new module name with a double colon C<::> separating the two. | |
1141 | ||
1142 | If you don't like the exact way that this is done, don't fret you do | |
1143 | have a couple of options. First, you can specify a L<DISPATCH TABLE> | |
1144 | which is much more powerful and flexible (in fact this default | |
1145 | behavior is actually implemented internally with a dispatch table). | |
1146 | Or if you want something a little simpler, you can simply subclass and | |
1147 | extend the L<translate_module_name> method. | |
1105 | 1148 | |
1106 | 1149 | =head2 Getting the run mode |
1107 | 1150 | |
1108 | Just like the module name is retrieved from splitting the path on slashes, so is the | |
1109 | run mode. Only instead of using the second element of the resulting list, we use the third | |
1110 | as the run mode. So, using the same example, if we have a path of | |
1151 | Just like the module name is retrieved from splitting the path on | |
1152 | slashes, so is the run mode. Only instead of using the second element | |
1153 | of the resulting list, we use the third as the run mode. So, using the | |
1154 | same example, if we have a path of | |
1111 | 1155 | |
1112 | 1156 | /module_name/mode2 |
1113 | 1157 | |
1119 | 1163 | |
1120 | 1164 | =item * CGI query strings |
1121 | 1165 | |
1122 | CGI query strings are unaffected by the use of C<PATH_INFO> to obtain the module name and run mode. | |
1123 | This means that any other modules you use to get access to you query argument (ie, L<CGI>, | |
1124 | L<Apache::Request>) should not be affected. But, since the run mode may be determined by | |
1125 | CGI::Application::Dispatch having a query argument named 'rm' will be ignored by your application | |
1126 | module. | |
1166 | CGI query strings are unaffected by the use of C<PATH_INFO> to obtain | |
1167 | the module name and run mode. This means that any other modules you | |
1168 | use to get access to you query argument (ie, L<CGI>, | |
1169 | L<Apache::Request>) should not be affected. But, since the run mode | |
1170 | may be determined by CGI::Application::Dispatch having a query | |
1171 | argument named 'rm' will be ignored by your application module. | |
1127 | 1172 | |
1128 | 1173 | =back |
1129 | 1174 | |
1133 | 1178 | |
1134 | 1179 | /cgi-bin/dispatch.cgi/module_name/run_mode |
1135 | 1180 | |
1136 | However, including "/cgi-bin/dispatch.cgi" in ever URL doesn't add any value to the URL, | |
1137 | so it's nice to remove it. This is easily done if you are using the Apache web server with | |
1138 | C<mod_rewrite> available. Adding the following to a C<.htaccess> file would allow you to | |
1139 | simply use: | |
1181 | However, including "/cgi-bin/dispatch.cgi" in ever URL doesn't add any | |
1182 | value to the URL, so it's nice to remove it. This is easily done if | |
1183 | you are using the Apache web server with C<mod_rewrite> | |
1184 | available. Adding the following to a C<.htaccess> file would allow you | |
1185 | to simply use: | |
1140 | 1186 | |
1141 | 1187 | /module_name/run_mode |
1142 | 1188 | |
1143 | If you have problems with mod_rewrite, turn on debugging to see exactly what's happening: | |
1189 | If you have problems with mod_rewrite, turn on debugging to see | |
1190 | exactly what's happening: | |
1144 | 1191 | |
1145 | 1192 | RewriteLog /home/project/logs/alpha-rewrite.log |
1146 | 1193 | RewriteLogLevel 9 |
1175 | 1222 | be treated as a directory, and also supports multiple developer directories, |
1176 | 1223 | so C</~mark> has its own separate dispatching system beneath it. |
1177 | 1224 | |
1178 | Note that order matters here! The Location block for "/" needs to come before the | |
1179 | user blocks. | |
1225 | Note that order matters here! The Location block for "/" needs to come | |
1226 | before the user blocks. | |
1180 | 1227 | |
1181 | 1228 | <Location /> |
1182 | 1229 | RewriteEngine On |
1201 | 1248 | # Run "/" through the dispatcher |
1202 | 1249 | RewriteRule ^/home/mark/www/$ /~mark/cgi-bin/dispatch.cgi [L,QSA] |
1203 | 1250 | |
1204 | # Otherwise, if an actual file or directory is requested, serve directly | |
1251 | # Otherwise, if an actual file or directory is requested, | |
1252 | # serve directly | |
1205 | 1253 | RewriteCond %{REQUEST_FILENAME} !-f |
1206 | 1254 | RewriteCond %{REQUEST_FILENAME} !-d |
1207 | 1255 | |
1208 | # Otherwise, pass everything through to the dispatcher | |
1256 | # Otherwise, pass everything through to the dispatcher | |
1209 | 1257 | RewriteRule ^(.*)$ /~mark/cgi-bin/dispatch.cgi/$1 [L,QSA] |
1210 | 1258 | |
1211 | 1259 | # These examples may also be helpful, but are unrelated to dispatching. |
1217 | 1265 | |
1218 | 1266 | =head1 SUBCLASSING |
1219 | 1267 | |
1220 | While Dispatch tries to be flexible, it won't be able to do everything that people want. Hopefully | |
1221 | we've made it flexible enough so that if it doesn't do I<The Right Thing> you can easily subclass | |
1222 | it. | |
1268 | While Dispatch tries to be flexible, it won't be able to do everything | |
1269 | that people want. Hopefully we've made it flexible enough so that if | |
1270 | it doesn't do I<The Right Thing> you can easily subclass it. | |
1223 | 1271 | |
1224 | 1272 | =cut |
1225 | 1273 | |
1226 | 1274 | #=head2 PROTECTED METHODS |
1227 | 1275 | # |
1228 | #The following methods are intended to be overridden by subclasses if necessary. They are not | |
1229 | #part of the public API since end users will never touch them. However, to ensure that your | |
1230 | #subclass of Dispatch does not break with a new release, they are documented here and are considered | |
1231 | #to be part of the API and will not be changed without very good reasons. | |
1276 | #The following methods are intended to be overridden by subclasses if | |
1277 | #necessary. They are not part of the public API since end users will | |
1278 | #never touch them. However, to ensure that your subclass of Dispatch | |
1279 | #does not break with a new release, they are documented here and are | |
1280 | #considered to be part of the API and will not be changed without very | |
1281 | #good reasons. | |
1232 | 1282 | |
1233 | 1283 | =head1 AUTHOR |
1234 | 1284 | |
1235 | 1285 | Michael Peters <mpeters@plusthree.com> |
1236 | 1286 | |
1237 | Thanks to Plus Three, LP (http://www.plusthree.com) for sponsoring my work on this module | |
1287 | Thanks to Plus Three, LP (http://www.plusthree.com) for sponsoring my | |
1288 | work on this module | |
1238 | 1289 | |
1239 | 1290 | =head1 COMMUNITY |
1240 | 1291 | |
1241 | This module is a part of the larger L<CGI::Application> community. If you have questions or | |
1242 | comments about this module then please join us on the cgiapp mailing list by sending a blank | |
1243 | message to "cgiapp-subscribe@lists.erlbaum.net". There is also a community wiki located at | |
1244 | L<http://www.cgi-app.org/> | |
1292 | This module is a part of the larger L<CGI::Application> community. If | |
1293 | you have questions or comments about this module then please join us | |
1294 | on the cgiapp mailing list by sending a blank message to | |
1295 | "cgiapp-subscribe@lists.erlbaum.net". There is also a community wiki | |
1296 | located at L<http://www.cgi-app.org/> | |
1245 | 1297 | |
1246 | 1298 | =head1 SOURCE CODE REPOSITORY |
1247 | 1299 | |
1280 | 1332 | |
1281 | 1333 | =head1 SECURITY |
1282 | 1334 | |
1283 | Since C::A::Dispatch will dynamically choose which modules to use as the content generators, | |
1284 | it may give someone the ability to execute random modules on your system if those modules can | |
1285 | be found in you path. Of course those modules would have to behave like L<CGI::Application> based | |
1286 | modules, but that still opens up the door more than most want. This should only be a problem | |
1287 | if you don't use a L<prefix>. By using this option you are only allowing Dispatch to pick from | |
1288 | a namespace of modules to run. | |
1335 | Since C::A::Dispatch will dynamically choose which modules to use as | |
1336 | the content generators, it may give someone the ability to execute | |
1337 | random modules on your system if those modules can be found in you | |
1338 | path. Of course those modules would have to behave like | |
1339 | L<CGI::Application> based modules, but that still opens up the door | |
1340 | more than most want. This should only be a problem if you don't use a | |
1341 | L<prefix>. By using this option you are only allowing Dispatch to pick | |
1342 | from a namespace of modules to run. | |
1289 | 1343 | |
1290 | 1344 | =head1 SEE ALSO |
1291 | 1345 |
0 | 0 | package MyApp::Module::Name; |
1 | 1 | use base 'CGI::Application'; |
2 | use HTTP::Exception; | |
2 | 3 | |
3 | 4 | sub setup { |
4 | 5 | my $self = shift; |
10 | 11 | rm4 |
11 | 12 | rm5 |
12 | 13 | local_args_to_new |
14 | throw_http_exception | |
13 | 15 | /]); |
16 | $self->error_mode('rethrow_http_exceptions'); | |
14 | 17 | } |
15 | 18 | |
16 | 19 | sub rm1 { |
57 | 60 | return $self->tmpl_path; |
58 | 61 | } |
59 | 62 | |
63 | sub throw_http_exception { | |
64 | HTTP::Exception->throw(405, status_message => 'my 405 exception!'); | |
65 | } | |
66 | ||
67 | sub rethrow_http_exceptions { | |
68 | my $self = shift; | |
69 | my $e = shift; | |
70 | ||
71 | # Duck-type to see if we have an HTTP::Exception | |
72 | if (defined $e && $e->can('status_method')) { | |
73 | die $e; | |
74 | } | |
75 | # In this case, just die then, too... | |
76 | else { | |
77 | die $e; | |
78 | } | |
79 | ||
80 | } | |
60 | 81 | |
61 | 82 | 1; |
2 | 2 | |
3 | 3 | sub setup { |
4 | 4 | my $self = shift; |
5 | $self->start_mode('rm1'); | |
5 | $self->start_mode('rm1_GET'); | |
6 | 6 | $self->run_modes([qw/ |
7 | 7 | rm1_GET |
8 | 8 | rm1_POST |
168 | 168 | 'named url remainder'; |
169 | 169 | }; |
170 | 170 | |
171 | # args_to_new | |
171 | # args_to_new, throwing HTTP::Exceptions | |
172 | 172 | test_psgi |
173 | 173 | app => CGI::Application::Dispatch::PSGI->as_psgi( |
174 | 174 | prefix => 'MyApp', |
177 | 177 | ), |
178 | 178 | client => sub { |
179 | 179 | my $cb = shift; |
180 | like | |
181 | $cb->(GET '/module_name/local_args_to_new')->content, | |
180 | ||
181 | # args_to_new | |
182 | like $cb->(GET '/module_name/local_args_to_new')->content, | |
182 | 183 | qr/events/, |
183 | 184 | 'args_to_new works'; |
185 | ||
186 | # When an HTTP::Exception is thrown from error_mode, it is passed through. | |
187 | my $res = $cb->(GET '/module_name/throw_http_exception'); | |
188 | is($res->code,405,"a thrown HTTP::Exception is bubbled up"); | |
189 | like($res->as_string, qr/my 405 exception/, "HTTP::Exception content is passed along"); | |
184 | 190 | }; |
185 | 191 | |
186 | 192 | # 404 |
196 | 202 | qr/404 not found/i, |
197 | 203 | }; |
198 | 204 | |
205 | # auto_rest | |
206 | test_psgi | |
207 | app => CGI::Application::Dispatch::PSGI->as_psgi( | |
208 | auto_rest => 1, | |
209 | prefix => 'MyApp', | |
210 | table => [ | |
211 | ':app/rm3[get]' => { rm => 'get_rm3', auto_rest => 0 }, | |
212 | ':app/rm4' => { auto_rest => 0, rm => 'rm4' }, | |
213 | ':app/rm2' => { auto_rest_lc => 1, rm => 'rm2' }, | |
214 | ':app/:rm?' => { }, | |
215 | ], | |
216 | ), | |
217 | client => sub { | |
218 | my $cb = shift; | |
219 | my $res = $cb->(GET '/module_rest/rm1'); | |
220 | ok($res->is_success); | |
221 | like($res->content, qr{MyApp::Module::Rest->rm1_GET}, 'auto_rest GET'); | |
222 | ||
223 | $res = $cb->(POST '/module_rest/rm1'); | |
224 | ok($res->is_success); | |
225 | like($res->content, qr{MyApp::Module::Rest->rm1_POST}, 'auto_rest POST'); | |
226 | ||
227 | $res = $cb->(POST '/module_rest/rm2'); | |
228 | ok($res->is_success); | |
229 | $content = $res->content; | |
230 | like($res->content, qr{App::Module::Rest->rm2_post}, 'auto_rest_lc POST'); | |
231 | ||
232 | $res = $cb->(GET '/module_rest/rm3'); | |
233 | ok($res->is_success); | |
234 | $content = $res->content; | |
235 | like($res->content, qr{App::Module::Rest->get_rm3}, 'HTTP method in rule'); | |
236 | ||
237 | $res = $cb->(GET '/module_rest/rm4'); | |
238 | ok($res->is_success); | |
239 | like($res->content, qr{App::Module::Rest->rm4}, 'non-auto_rest GET'); | |
240 | unlike($res->content, qr{App::Module::Rest->rm4_GET}, 'non-auto_rest GET'); | |
241 | ||
242 | $res = $cb->(POST '/module_rest/rm4'); | |
243 | ok($res->is_success); | |
244 | like($res->content, qr{App::Module::Rest->rm4}, 'non-auto_rest POST'); | |
245 | unlike($res->content, qr{App::Module::Rest->rm4_POST}, 'non-auto_rest POST'); | |
246 | ||
247 | $res = $cb->(GET '/module_rest'); | |
248 | ok($res->is_success); | |
249 | like($res->content, qr{MyApp::Module::Rest->rm1_GET}, 'auto_rest check of /:rm? and start_mode'); | |
250 | }; | |
251 | ||
199 | 252 | # restore STDERR |
200 | 253 | { |
201 | 254 | close STDERR; |