1CGI::Application::DispaUtscehr::CPoSnGtIr(i3bpumt)ed PerClGID:o:cAupmpelnitcaattiioonn::Dispatch::PSGI(3pm)
2
3
4

NAME

6       CGI::Application::Dispatch::PSGI - Dispatch requests to
7       CGI::Application based objects using PSGI
8

SYNOPSIS

10   Out of Box
11       Under mod_perl:
12
13         # change "Apache1" to "Apache2" as needed.
14
15         <Location />
16         SetHandler perl-script
17         PerlHandler Plack::Handler::Apache1
18         PerlSetVar psgi_app /path/to/app.psgi
19         </Location>
20
21         <Perl>
22         use Plack::Handler::Apache1;
23         Plack::Handler::Apache1->preload("/path/to/app.psgi");
24         </Perl>
25
26       Under CGI:
27
28       This would be the instance script for your application, such as
29       /cgi-bin/dispatch.cgi:
30
31           ### in your dispatch.psgi:
32           # ( in a persistent environment, use FindBin::Real instead. )
33           use FindBin 'Bin';
34           use lib "$Bin/../perllib';
35           use Your::Application::Dispatch;
36           Your::Application::Dispatch->as_psgi;
37
38           ### In Your::Application::Dispatch;
39           package Your::Application::Dispatch;
40           use base 'CGI::Application::Dispatch::PSGI';
41
42   With a dispatch table
43           package MyApp::Dispatch;
44           use base 'CGI::Application::Dispatch::PSGI';
45
46           sub dispatch_args {
47               return {
48                   prefix  => 'MyApp',
49                   table   => [
50                       ''                => { app => 'Welcome', rm => 'start' },
51                       ':app/:rm'        => { },
52                       'admin/:app/:rm'  => { prefix   => 'MyApp::Admin' },
53                   ],
54               };
55           }
56
57       The ".psgi" file is constructed as above.
58
59   With a custom query object
60       If you want to supply your own PSGI object, something like this in your
61       .psgi file will work:
62
63           sub {
64               my $env = shift;
65               my $app = CGI::Application::Dispatch::PSGI->as_psgi(
66                   table => [
67                       '/:rm'    =>    { app => 'TestApp' }
68                   ],
69                   args_to_new => {
70                       QUERY    => CGI::PSGI->new($env)
71                   }
72               );
73               return $app->($env);
74           }
75

DESCRIPTION

77       This module provides a way to look at the path (as returned by
78       "$env->{PATH_INFO}") of the incoming request, parse off the desired
79       module and its run mode, create an instance of that module and run it.
80
81       It will translate a URI like this (in a persistent environment)
82
83           /app/module_name/run_mode
84
85       or this (vanilla CGI)
86
87           /app/index.cgi/module_name/run_mode
88
89       into something that will be functionally similar to this
90
91           my $app = Module::Name->new(..);
92           $app->mode_param(sub {'run_mode'}); #this will set the run mode
93

METHODS

95   as_psgi(%args)
96       This is the primary method used during dispatch.
97
98           #!/usr/bin/perl
99           use strict;
100           use CGI::Application::Dispatch::PSGI;
101
102           CGI::Application::Dispatch::PSGI->as_psgi(
103               prefix  => 'MyApp',
104               default => 'module_name',
105           );
106
107       This method accepts the following name value pairs:
108
109       default
110           Specify a value to use for the path if one is not available.  This
111           could be the case if the default page is selected (eg: "/" ).
112
113       prefix
114           This option will set the string that will be prepended to the name
115           of the application module before it is loaded and created. So to
116           use our previous example request of
117
118               /app/index.cgi/module_name/run_mode
119
120           This would by default load and create a module named
121           'Module::Name'. But let's say that you have all of your application
122           specific modules under the 'My' namespace. If you set this option
123           to 'My' then it would instead load the 'My::Module::Name'
124           application module instead.
125
126       args_to_new
127           This is a hash of arguments that are passed into the new()
128           constructor of the application.
129
130       table
131           In most cases, simply using Dispatch with the "default" and
132           "prefix" is enough to simplify your application and your URLs, but
133           there are many cases where you want more power. Enter the dispatch
134           table. Since this table can be slightly complicated, a whole
135           section exists on its use. Please see the "DISPATCH TABLE" section.
136
137       debug
138           Set to a true value to send debugging output for this module to
139           STDERR. Off by default.
140
141       auto_rest
142           This tells Dispatch that you are using REST by default and that you
143           care about which HTTP method is being used. Dispatch will append
144           the HTTP method name (upper case by default) to the run mode that
145           is determined after finding the appropriate dispatch rule. So a GET
146           request that translates into "MyApp::Module->foo" will become
147           "MyApp::Module->foo_GET".
148
149           This can be overridden on a per-rule basis in a custom dispatch
150           table.
151
152       auto_rest_lc
153           In combinaion with auto_rest this tells Dispatch that you prefer
154           lower cased HTTP method names.  So instead of "foo_POST" and
155           "foo_GET" you'll have "foo_post" and "foo_get".
156
157   dispatch_args()
158       Returns a hashref of args that will be passed to dispatch(). It will
159       return the following structure by default.
160
161           {
162               prefix      => '',
163               args_to_new => {},
164               table       => [
165                   ':app'      => {},
166                   ':app/:rm'  => {},
167               ],
168           }
169
170       This is the perfect place to override when creating a subclass to
171       provide a richer dispatch table.
172
173       When called, it receives 1 argument, which is a reference to the hash
174       of args passed into dispatch.
175
176   translate_module_name($input)
177       This method is used to control how the module name is translated from
178       the matching section of the path (see "Path Parsing".  The main reason
179       that this method exists is so that it can be overridden if it doesn't
180       do exactly what you want.
181
182       The following transformations are performed on the input:
183
184       The text is split on '_'s (underscores) and each word has its first
185       letter capitalized. The words are then joined back together and each
186       instance of an underscore is replaced by '::'.
187       The text is split on '-'s (hyphens) and each word has its first letter
188       capitalized. The words are then joined back together and each instance
189       of a hyphen removed.
190
191       Here are some examples to make it even clearer:
192
193           module_name         => Module::Name
194           module-name         => ModuleName
195           admin_top-scores    => Admin::TopScores
196
197   require_module($module_name)
198       This class method is used internally to take a module name (supplied by
199       get_module_name) and require it in a secure fashion. It is provided as
200       a public class method so that if you override other functionality of
201       this module, you can still safely require user specified modules. If
202       there are any problems requiring the named module, then we will
203       "croak".
204
205           CGI::Application::Dispatch::PSGI->require_module('MyApp::Module::Name');
206

DISPATCH TABLE

208       Sometimes it's easiest to explain with an example, so here you go:
209
210         CGI::Application::Dispatch::PSGI->as_psgi(
211           prefix      => 'MyApp',
212           args_to_new => {
213               TMPL_PATH => 'myapp/templates'
214           },
215           table       => [
216               ''                         => { app => 'Blog', rm => 'recent'},
217               'posts/:category'          => { app => 'Blog', rm => 'posts' },
218               ':app/:rm/:id'             => { app => 'Blog' },
219               'date/:year/:month?/:day?' => {
220                   app         => 'Blog',
221                   rm          => 'by_date',
222                   args_to_new => { TMPL_PATH => "events/" },
223               },
224           ]
225         );
226
227       So first, this call to as_psgi sets the prefix and passes a "TMPL_PATH"
228       into args_to_new. Next it sets the table.
229
230   VOCABULARY
231       Just so we all understand what we're talking about....
232
233       A table is an array where the elements are gouped as pairs (similar to
234       a hash's key-value pairs, but as an array to preserve order). The first
235       element of each pair is called a "rule". The second element in the pair
236       is called the rule's "arg list".  Inside a rule there are slashes "/".
237       Anything set of characters between slashes is called a "token".
238
239   URL MATCHING
240       When a URL comes in, Dispatch tries to match it against each rule in
241       the table in the order in which the rules are given. The first one to
242       match wins.
243
244       A rule consists of slashes and tokens. A token can one of the following
245       types:
246
247       literal
248           Any token which does not start with a colon (":") is taken to be a
249           literal string and must appear exactly as-is in the URL in order to
250           match. In the rule
251
252               'posts/:category'
253
254           "posts" is a literal token.
255
256       variable
257           Any token which begins with a colon (":") is a variable token.
258           These are simply wild-card place holders in the rule that will
259           match anything in the URL that isn't a slash. These variables can
260           later be referred to by using the "$self->param" mechanism. In the
261           rule
262
263               'posts/:category'
264
265           ":category" is a variable token. If the URL matched this rule, then
266           you could the value of that token from whithin your application
267           like so:
268
269               my $category = $self->param('category');
270
271           There are some variable tokens which are special. These can be used
272           to further customize the dispatching.
273
274           :app
275               This is the module name of the application. The value of this
276               token will be sent to the translate_module_name method and then
277               prefixed with the prefix if there is one.
278
279           :rm This is the run mode of the application. The value of this
280               token will be the actual name of the run mode used. The run
281               mode can be optional, as noted below. Example:
282
283                   /foo/:rm?
284
285               If no run mode is found, it will default to using the
286               start_mode(), just like invoking CGI::Application directly.
287               Both of these URLs would end up dispatching to the start mode
288               associated with /foo:
289
290                   /foo/
291                   /foo
292
293       optional-variable
294           Any token which begins with a colon (":") and ends with a question
295           mark (<?>) is considered optional. If the rest of the URL matches
296           the rest of the rule, then it doesn't matter whether it contains
297           this token or not. It's best to only include optional-variable
298           tokens at the end of your rule. In the rule
299
300               'date/:year/:month?/:day?'
301
302           ":month?" and ":day?" are optional-variable tokens.
303
304           Just like with variable tokens, optional-variable tokens' values
305           can also be retrieved by the application, if they existed in the
306           URL.
307
308               if( defined $self->param('month') ) {
309                   ...
310               }
311
312       wildcard
313           The wildcard token "*" allows for partial matches. The token MUST
314           appear at the end of the rule.
315
316             'posts/list/*'
317
318           By default, the "dispatch_url_remainder" param is set to the
319           remainder of the URL matched by the *. The name of the param can be
320           changed by setting "*" argument in the "ARG LIST".
321
322             'posts/list/*' => { '*' => 'post_list_filter' }
323
324       method
325           You can also dispatch based on HTTP method. This is similar to
326           using auto_rest but offers more fine grained control. You include
327           the method (case insensitive) at the end of the rule and enclose it
328           in square brackets.
329
330             ':app/news[post]'   => { rm => 'add_news'    },
331             ':app/news[get]'    => { rm => 'news'        },
332             ':app/news[delete]' => { rm => 'delete_news' },
333
334       The main reason that we don't use regular expressions for dispatch
335       rules is that regular expressions provide no mechanism for named back
336       references, like variable tokens do.
337
338   ARG LIST
339       Each rule can have an accompanying arg-list. This arg list can contain
340       special arguments that override something set higher up in dispatch for
341       this particular URL, or just have additional args passed available in
342       "$self->param()"
343
344       For instance, if you want to override prefix for a specific rule, then
345       you can do so.
346
347           'admin/:app/:rm' => { prefix => 'MyApp::Admin' },
348

Path Parsing

350       This section will describe how the application module and run mode are
351       determined from the path if no "DISPATCH TABLE" is present, and what
352       options you have to customize the process.  The value for the path to
353       be parsed is retrieved from "$env->{PATH_INFO}".
354
355   Getting the module name
356       To get the name of the application module the path is split on
357       backslahes ("/").  The second element of the returned list (the first
358       is empty) is used to create the application module. So if we have a
359       path of
360
361           /module_name/mode1
362
363       then the string 'module_name' is used. This is passed through the
364       translate_module_name method. Then if there is a "prefix" (and there
365       should always be a prefix) it is added to the beginning of this new
366       module name with a double colon "::" separating the two.
367
368       If you don't like the exact way that this is done, don't fret you do
369       have a couple of options.  First, you can specify a "DISPATCH TABLE"
370       which is much more powerful and flexible (in fact this default behavior
371       is actually implemented internally with a dispatch table).  Or if you
372       want something a little simpler, you can simply subclass and extend the
373       translate_module_name method.
374
375   Getting the run mode
376       Just like the module name is retrieved from splitting the path on
377       slashes, so is the run mode. Only instead of using the second element
378       of the resulting list, we use the third as the run mode. So, using the
379       same example, if we have a path of
380
381           /module_name/mode2
382
383       Then the string 'mode2' is used as the run mode.
384

Exception Handling

386       A CGI::Application object can throw an exception up to
387       "CGI::Application::Dispatch::PSGI" if no error_mode() is implemented or
388       if the error_mode itself throws an exception. In these cases we
389       generally return a generic "500" response, and log some details for the
390       developer with a warning.
391
392       However, we will check to see if the exception thrown is an
393       HTTP::Exception object. If that's the case, we will rethrow it, and you
394       can handle it yourself using something like
395       Plack::Middleware::HTTPExceptions.
396

MISC NOTES

398       •       CGI query strings
399
400               CGI query strings are unaffected by the use of "PATH_INFO" to
401               obtain the module name and run mode.  This means that any other
402               modules you use to get access to you query argument (ie, CGI,
403               Apache::Request) should not be affected. But, since the run
404               mode may be determined by CGI::Application::Dispatch::PSGI
405               having a query argument named 'rm' will be ignored by your
406               application module.
407

CLEAN URLS WITH MOD_REWRITE

409       With a dispatch script, you can fairly clean URLS like this:
410
411        /cgi-bin/dispatch.cgi/module_name/run_mode
412
413       However, including "/cgi-bin/dispatch.cgi" in ever URL doesn't add any
414       value to the URL, so it's nice to remove it. This is easily done if you
415       are using the Apache web server with "mod_rewrite" available. Adding
416       the following to a ".htaccess" file would allow you to simply use:
417
418        /module_name/run_mode
419
420       If you have problems with mod_rewrite, turn on debugging to see exactly
421       what's happening:
422
423        RewriteLog /home/project/logs/alpha-rewrite.log
424        RewriteLogLevel 9
425
426   mod_rewrite related code in the dispatch script.
427       This seemed necessary to put in the dispatch script to make mod_rewrite
428       happy.  Perhaps it's specific to using "RewriteBase".
429
430         # mod_rewrite alters the PATH_INFO by turning it into a file system path,
431         # so we repair it.
432         $ENV{PATH_INFO} =~ s/^$ENV{DOCUMENT_ROOT}// if defined $ENV{PATH_INFO};
433
434   Simple Apache Example
435         RewriteEngine On
436
437         # You may want to change the base if you are using the dispatcher within a
438         # specific directory.
439         RewriteBase /
440
441         # If an actual file or directory is requested, serve directly
442         RewriteCond %{REQUEST_FILENAME} !-f
443         RewriteCond %{REQUEST_FILENAME} !-d
444
445         # Otherwise, pass everything through to the dispatcher
446         RewriteRule ^(.*)$ /cgi-bin/dispatch.cgi/$1 [L,QSA]
447
448   More complex rewrite: dispatching "/" and multiple developers
449       Here is a more complex example that dispatches "/", which would
450       otherwise be treated as a directory, and also supports multiple
451       developer directories, so "/~mark" has its own separate dispatching
452       system beneath it.
453
454       Note that order matters here! The Location block for "/" needs to come
455       before the user blocks.
456
457         <Location />
458           RewriteEngine On
459           RewriteBase /
460
461           # Run "/" through the dispatcher
462           RewriteRule ^home/project/www/$ /cgi-bin/dispatch.cgi [L,QSA]
463
464           # Don't apply this rule to the users sub directories.
465           RewriteCond %{REQUEST_URI} !^/~.*$
466           # If an actual file or directory is requested, serve directly
467           RewriteCond %{REQUEST_FILENAME} !-f
468           RewriteCond %{REQUEST_FILENAME} !-d
469           # Otherwise, pass everything through to the dispatcher
470           RewriteRule ^(.*)$ /cgi-bin/dispatch.cgi/$1 [L,QSA]
471         </Location>
472
473         <Location /~mark>
474           RewriteEngine On
475           RewriteBase /~mark
476
477           # Run "/" through the dispatcher
478           RewriteRule ^/home/mark/www/$ /~mark/cgi-bin/dispatch.cgi [L,QSA]
479
480           # Otherwise, if an actual file or directory is requested, serve directly
481           RewriteCond %{REQUEST_FILENAME} !-f
482           RewriteCond %{REQUEST_FILENAME} !-d
483
484           # Otherwise, pass everything through to the dispatcher
485           RewriteRule ^(.*)$ /~mark/cgi-bin/dispatch.cgi/$1 [L,QSA]
486
487           # These examples may also be helpful, but are unrelated to dispatching.
488           SetEnv DEVMODE mark
489           SetEnv PERL5LIB /home/mark/perllib:/home/mark/config
490           ErrorDocument 404 /~mark/errdocs/404.html
491           ErrorDocument 500 /~mark/errdocs/500.html
492         </Location>
493

SUBCLASSING

495       While Dispatch tries to be flexible, it won't be able to do everything
496       that people want. Hopefully we've made it flexible enough so that if it
497       doesn't do The Right Thing you can easily subclass it.
498

AUTHORS

500       Mark Stosberg <mark@summersault.com>
501
502       Heavily based on CGI::Application::Dispatch, written by Michael Peters
503       <mpeters@plusthree.com> and others
504

COMMUNITY

506       This module is a part of the larger CGI::Application community. If you
507       have questions or comments about this module then please join us on the
508       cgiapp mailing list by sending a blank message to
509       "cgiapp-subscribe@lists.erlbaum.net". There is also a community wiki
510       located at <http://www.cgi-app.org/>
511

SOURCE CODE REPOSITORY

513       A public source code repository for this project is hosted here:
514
515       https://github.com/markstos/CGI--Application--Dispatch
516

SECURITY

518       Since C::A::Dispatch::PSGI will dynamically choose which modules to use
519       as the content generators, it may give someone the ability to execute
520       random modules on your system if those modules can be found in you
521       path. Of course those modules would have to behave like
522       CGI::Application based modules, but that still opens up the door more
523       than most want. This should only be a problem if you don't use a
524       prefix. By using this option you are only allowing Dispatch to pick
525       from a namespace of modules to run.
526

Backwards Compatibility

528       Versions 0.2 and earlier of this module injected the "as_psgi" method
529       into CGI::Application::Dispatch, creating a syntax like this:
530
531          ### in your dispatch.psgi:
532          use Your::Application::Dispatch;
533          use CGI::Application::Dispatch::PSGI;
534          Your::Application::Dispatch->as_psgi;
535
536          ### In Your::Application::Dispatch;
537          use base 'CGI::Application::Dispatch::PSGI';
538
539       In the current design, the "as_pgsi" method is directly in this module,
540       so a couple of lines of code need to be changed:
541
542          ### in your dispatch.psgi:
543          use Your::Application::Dispatch;
544          Your::Application::Dispatch->as_psgi;
545
546          ### In Your::Application::Dispatch;
547          use base 'CGI::Application::Dispatch::PSGI';
548

Differences with CGI::Application::Dispatch

550       dispatch()
551           Use as_psgi() instead.
552
553           Note that the "error_document" key is not supported here. Use the
554           Plack::Middleware::ErrorDocument or another PSGI solution instead.
555
556       dispatch_path()
557           The dispatch_path() method is not supported. The alternative is to
558           reference "$env->{PATH_INFO}" which is available per the PSGI spec.
559
560       handler()
561           This provided an Apache-specific handler. Other PSGI components
562           like Plack::Handler::Apache2 provide Apache handlers now instead.
563
564       _http_method()
565           This method has been eliminated. Check "$env->{REQUEST_METHOD}"
566           directly instead.
567
568       _parse_path()
569           The private _parse_path() method now accepts an additional
570           argument, the PSGI $env hash.
571
572       _run_app()
573           The private _run_app() method now accepts an additional argument,
574           the PSGI $env hash.
575
576       _r()
577           This method has been eliminated. It does not apply in PSGI.
578

SEE ALSO

580       CGI::Application, Apache::Dispatch
581
583       Copyright Michael Peters and Mark Stosberg 2008-2010, all rights
584       reserved.
585
586       This library is free software; you can redistribute it and/or modify it
587       under the same terms as Perl itself.
588
589
590
591perl v5.38.0                      2023-07-C2G0I::Application::Dispatch::PSGI(3pm)
Impressum