some doc cleanup
[catagits/Web-Simple.git] / lib / Web / Simple.pm
CommitLineData
5c33dda5 1package Web::Simple;
2
8bd060f4 3use strictures 1;
8c4ffad3 4use 5.008;
8bd060f4 5use warnings::illegalproto ();
876e62e1 6use Moo ();
7use Web::Dispatch::Wrapper ();
8c4ffad3 8
1cf4503c 9our $VERSION = '0.020';
5c33dda5 10
44db8e76 11sub import {
5c33dda5 12 my ($class, $app_package) = @_;
876e62e1 13 $app_package ||= caller;
14 $class->_export_into($app_package);
15 eval "package $app_package; use Web::Dispatch::Wrapper; use Moo; 1"
16 or die "Failed to setup app package: $@";
445b3ea0 17 strictures->import;
8bd060f4 18 warnings::illegalproto->unimport;
5c33dda5 19}
20
21sub _export_into {
22 my ($class, $app_package) = @_;
23 {
24 no strict 'refs';
c7b1c57f 25 *{"${app_package}::PSGI_ENV"} = sub () { -1 };
5c33dda5 26 require Web::Simple::Application;
27 unshift(@{"${app_package}::ISA"}, 'Web::Simple::Application');
28 }
b7063124 29 (my $name = $app_package) =~ s/::/\//g;
30 $INC{"${name}.pm"} = 'Set by "use Web::Simple;" invocation';
5c33dda5 31}
32
fd6d986e 331;
34823486 34
7401408e 35=head1 NAME
36
37Web::Simple - A quick and easy way to build simple web applications
38
7401408e 39
40=head1 SYNOPSIS
41
05ad188d 42 #!/usr/bin/env perl
7401408e 43
4f83bde7 44 package HelloWorld;
6ee6b2dc 45 use Web::Simple;
4f83bde7 46
47 sub dispatch_request {
48 sub (GET) {
49 [ 200, [ 'Content-type', 'text/plain' ], [ 'Hello world!' ] ]
50 },
51 sub () {
52 [ 405, [ 'Content-type', 'text/plain' ], [ 'Method not allowed' ] ]
445b3ea0 53 }
7401408e 54 }
55
56 HelloWorld->run_if_script;
57
05ad188d 58If you save this file into your cgi-bin as C<hello-world.cgi> and then visit:
7401408e 59
60 http://my.server.name/cgi-bin/hello-world.cgi/
61
4f83bde7 62you'll get the "Hello world!" string output to your browser. At the same time
63this file will also act as a class module, so you can save it as HelloWorld.pm
64and use it as-is in test scripts or other deployment mechanisms.
65
582ee8ea 66Note that you should retain the C<< ->run_if_script >> even if your app is a
ca30a017 67module, since this additionally makes it valid as a .psgi file, which can
68be extremely useful during development.
69
4f83bde7 70For more complex examples and non-CGI deployment, see
71L<Web::Simple::Deployment>. To get help with L<Web::Simple>, please connect to
72the irc.perl.org IRC network and join #web-simple.
7401408e 73
fb771406 74=head1 DESCRIPTION
7401408e 75
6a4808bf 76The philosophy of L<Web::Simple> is to keep to an absolute bare minimum for
7401408e 77everything. It is not designed to be used for large scale applications;
78the L<Catalyst> web framework already works very nicely for that and is
79a far more mature, well supported piece of software.
80
81However, if you have an application that only does a couple of things, and
3895385d 82want to not have to think about complexities of deployment, then L<Web::Simple>
7401408e 83might be just the thing for you.
84
6a4808bf 85The only public interface the L<Web::Simple> module itself provides is an
86C<import> based one:
7401408e 87
88 use Web::Simple 'NameOfApplication';
89
6a4808bf 90This sets up your package (in this case "NameOfApplication" is your package)
3895385d 91so that it inherits from L<Web::Simple::Application> and imports L<strictures>,
38d5b336 92as well as installs a C<PSGI_ENV> constant for convenience, as well as some
3895385d 93other subroutines.
94
6a4808bf 95Importing L<strictures> will automatically make your code use the C<strict> and
3895385d 96C<warnings> pragma, so you can skip the usual:
7401408e 97
98 use strict;
3895385d 99 use warnings FATAL => 'aa';
7401408e 100
101provided you 'use Web::Simple' at the top of the file. Note that we turn
582ee8ea 102on B<fatal> warnings so if you have any warnings at any point from the file
7401408e 103that you did 'use Web::Simple' in, then your application will die. This is,
104so far, considered a feature.
105
a5006b25 106When we inherit from L<Web::Simple::Application> we also use L<Moo>, which is
582ee8ea 107the equivalent of:
7401408e 108
109 {
110 package NameOfApplication;
445b3ea0 111 use Moo;
112 extends 'Web::Simple::Application';
7401408e 113 }
114
6a4808bf 115So you can use L<Moo> features in your application, such as creating attributes
116using the C<has> subroutine, etc. Please see the documentation for L<Moo> for
117more information.
118
445b3ea0 119It also exports the following subroutines for use in dispatchers:
7401408e 120
74afe4b7 121 response_filter { ... };
7401408e 122
123 redispatch_to '/somewhere';
124
b7063124 125Finally, import sets
126
127 $INC{"NameOfApplication.pm"} = 'Set by "use Web::Simple;" invocation';
128
129so that perl will not attempt to load the application again even if
130
131 require NameOfApplication;
132
133is encountered in other code.
134
20645c5f 135One important thing to remember when using
136
137 NameOfApplication->run_if_script;
138
139At the end of your app is that this call will create an instance of your app
140for you automatically, regardless of context. An easier way to think of this
141would be if the method were more verbosely named
142
143 NameOfApplication->run_request_if_script_else_turn_coderef_for_psgi;
144
3583ca04 145=head1 DISPATCH STRATEGY
146
6a4808bf 147L<Web::Simple> despite being straightforward to use, has a powerful system
3895385d 148for matching all sorts of incoming URLs to one or more subroutines. These
149subroutines can be simple actions to take for a given URL, or something
150more complicated, including entire L<Plack> applications, L<Plack::Middleware>
151and nested subdispatchers.
152
c21c9f07 153=head2 Examples
154
445b3ea0 155 sub dispatch_request {
c21c9f07 156 # matches: GET /user/1.htm?show_details=1
157 # GET /user/1.htm
158 sub (GET + /user/* + ?show_details~ + .htm|.html|.xhtml) {
c254b30e 159 my ($self, $user_id, $show_details) = @_;
c21c9f07 160 ...
161 },
162 # matches: POST /user?username=frew
163 # POST /user?username=mst&first_name=matt&last_name=trout
164 sub (POST + /user + ?username=&*) {
c254b30e 165 my ($self, $username, $misc_params) = @_;
c21c9f07 166 ...
167 },
168 # matches: DELETE /user/1/friend/2
169 sub (DELETE + /user/*/friend/*) {
c254b30e 170 my ($self, $user_id, $friend_id) = @_;
c21c9f07 171 ...
172 },
173 # matches: PUT /user/1?first_name=Matt&last_name=Trout
174 sub (PUT + /user/* + ?first_name~&last_name~) {
c254b30e 175 my ($self, $user_id, $first_name, $last_name) = @_;
c21c9f07 176 ...
177 },
178 sub (/user/*/...) {
445b3ea0 179 my $user_id = $_[1];
180 # matches: PUT /user/1/role/1
181 sub (PUT + /role/*) {
182 my $role_id = $_[1];
183 ...
184 },
185 # matches: DELETE /user/1/role/1
186 sub (DELETE + /role/*) {
187 my $role_id = $_[1];
188 ...
189 },
c21c9f07 190 },
191 }
192
3706e2a0 193=head2 The dispatch cycle
81a5b03e 194
3706e2a0 195At the beginning of a request, your app's dispatch_request method is called
196with the PSGI $env as an argument. You can handle the request entirely in
197here and return a PSGI response arrayref if you want:
81a5b03e 198
3706e2a0 199 sub dispatch_request {
200 my ($self, $env) = @_;
201 [ 404, [ 'Content-type' => 'text/plain' ], [ 'Amnesia == fail' ] ]
202 }
81a5b03e 203
3706e2a0 204However, generally, instead of that, you return a set of dispatch subs:
81a5b03e 205
3706e2a0 206 sub dispatch_request {
207 my $self = shift;
208 sub (/) { redispatch_to '/index.html' },
209 sub (/user/*) { $self->show_user($_[1]) },
210 ...
211 }
81a5b03e 212
e927492b 213Well, a sub is a valid PSGI response too (for ultimate streaming and async
214cleverness). If you want to return a PSGI sub you have to wrap it into an
215array ref.
216
217 sub dispatch_request {
20645c5f 218 [ sub {
e927492b 219 my $respond = shift;
220 # This is pure PSGI here, so read perldoc PSGI
221 } ]
222 }
223
3706e2a0 224If you return a subroutine with a prototype, the prototype is treated
225as a match specification - and if the test is passed, the body of the
65e03df0 226sub is called as a method and passed any matched arguments (see below for more details).
81a5b03e 227
65e03df0 228You can also return a plain subroutine which will be called with just C<$env>
229- remember that in this case if you need C<$self> you B<must> close over it.
81a5b03e 230
3895385d 231If you return a normal object, L<Web::Simple> will simply return it upwards on
232the assumption that a response_filter (or some arbitrary L<Plack::Middleware>)
233somewhere will convert it to something useful. This allows:
81a5b03e 234
3706e2a0 235 sub dispatch_request {
236 my $self = shift;
237 sub (.html) { response_filter { $self->render_zoom($_[0]) } },
238 sub (/user/*) { $self->users->get($_[1]) },
239 }
81a5b03e 240
20645c5f 241An alternative to using prototypes to declare a match specification for a given
582ee8ea 242route is to provide a L<Dancer>-like key-value list:
20645c5f 243
244 sub dispatch_request {
245 my $self = shift;
246 (
247 '.html' => sub { response_filter { $self->render_zoom($_[0]) } },
248 '/user/*' => sub { $self->users->get($_[1]) }<
249 )
250 }
251
252This can be useful in situations where you are generating a dispatch table
582ee8ea 253programmatically, where setting a subroutine's protoype is difficult.
20645c5f 254
3895385d 255to render a user object to HTML, if there is an incoming URL such as:
256
257 http://myweb.org/user/111.html
258
259This works because as we descend down the dispachers, we first match
260C<sub (.html)>, which adds a C<response_filter> (basically a specialized routine
261that follows the L<Plack::Middleware> specification), and then later we also
262match C<sub (/user/*)> which gets a user and returns that as the response.
582ee8ea 263This user object "bubbles up" through all the wrapping middleware until it hits
3895385d 264the C<response_filter> we defined, after which the return is converted to a
265true html response.
81a5b03e 266
582ee8ea 267However, two types of objects are treated specially - a L<Plack::Component> object
65e03df0 268will have its C<to_app> method called and be used as a dispatcher:
81a5b03e 269
3706e2a0 270 sub dispatch_request {
271 my $self = shift;
272 sub (/static/...) { Plack::App::File->new(...) },
273 ...
81a5b03e 274 }
275
65e03df0 276A L<Plack::Middleware> object will be used as a filter for the rest of the
3706e2a0 277dispatch being returned into:
81a5b03e 278
6af22ff2 279 ## responds to /admin/track_usage AND /admin/delete_accounts
280
3706e2a0 281 sub dispatch_request {
282 my $self = shift;
6af22ff2 283 sub (/admin/**) {
284 Plack::Middleware::Session->new(%opts);
285 },
286 sub (/admin/track_usage) {
287 ## something that needs a session
288 },
289 sub (/admin/delete_accounts) {
290 ## something else that needs a session
291 },
81a5b03e 292 }
293
65e03df0 294Note that this is for the dispatch being B<returned> to, so if you want to
3706e2a0 295provide it inline you need to do:
81a5b03e 296
6af22ff2 297 ## ALSO responds to /admin/track_usage AND /admin/delete_accounts
298
3706e2a0 299 sub dispatch_request {
300 my $self = shift;
3706e2a0 301 sub (/admin/...) {
6af22ff2 302 sub {
303 Plack::Middleware::Session->new(%opts);
304 },
305 sub (/track_usage) {
306 ## something that needs a session
307 },
308 sub (/delete_accounts) {
309 ## something else that needs a session
310 },
3706e2a0 311 }
81a5b03e 312 }
313
3706e2a0 314And that's it - but remember that all this happens recursively - it's
3895385d 315dispatchers all the way down. A URL incoming pattern will run all matching
316dispatchers and then hit all added filters or L<Plack::Middleware>.
3706e2a0 317
81a5b03e 318=head2 Web::Simple match specifications
319
320=head3 Method matches
321
93e30ba3 322 sub (GET) {
15dfe701 323
324A match specification beginning with a capital letter matches HTTP requests
325with that request method.
326
81a5b03e 327=head3 Path matches
328
15dfe701 329 sub (/login) {
330
582ee8ea 331A match specification beginning with a C</> is a path match. In the simplest
15dfe701 332case it matches a specific path. To match a path with a wildcard part, you
333can do:
334
335 sub (/user/*) {
336 $self->handle_user($_[1])
337
338This will match /user/<anything> where <anything> does not include a literal
582ee8ea 339C</> character. The matched part becomes part of the match arguments. You can
15dfe701 340also match more than one part:
341
342 sub (/user/*/*) {
343 my ($self, $user_1, $user_2) = @_;
344
345 sub (/domain/*/user/*) {
346 my ($self, $domain, $user) = @_;
347
65e03df0 348and so on. To match an arbitrary number of parts, use C<**>:
15dfe701 349
350 sub (/page/**) {
1d02a8ae 351 my ($self, $match) = @_;
15dfe701 352
1d02a8ae 353This will result in a single element for the entire match. Note that you can do
15dfe701 354
355 sub (/page/**/edit) {
356
357to match an arbitrary number of parts up to but not including some final
358part.
359
65e03df0 360Note: Since Web::Simple handles a concept of file extensions, C<*> and C<**>
e060a690 361matchers will not by default match things after a final dot, and this
65e03df0 362can be modified by using C<*.*> and C<**.*> in the final position, e.g.:
e060a690 363
364 /one/* matches /one/two.three and captures "two"
365 /one/*.* matches /one/two.three and captures "two.three"
366 /** matches /one/two.three and captures "one/two"
367 /**.* matches /one/two.three and captures "one/two.three"
368
da8429c9 369Finally,
370
371 sub (/foo/...) {
372
65e03df0 373Will match C</foo/> on the beginning of the path B<and> strip it. This is
e060a690 374designed to be used to construct nested dispatch structures, but can also prove
375useful for having e.g. an optional language specification at the start of a
376path.
da8429c9 377
582ee8ea 378Note that the C<...> is a "maybe something here, maybe not" so the above
da8429c9 379specification will match like this:
380
381 /foo # no match
382 /foo/ # match and strip path to '/'
383 /foo/bar/baz # match and strip path to '/bar/baz'
384
e060a690 385Almost the same,
15e679c1 386
e060a690 387 sub (/foo...) {
388
389Will match on C</foo/bar/baz>, but also include C</foo>. Otherwise it
390operates the same way as C</foo/...>.
391
392 /foo # match and strip path to ''
393 /foo/ # match and strip path to '/'
394 /foo/bar/baz # match and strip path to '/bar/baz'
395
396Please note the difference between C<sub(/foo/...)> and C<sub(/foo...)>. In
397the first case, this is expecting to find something after C</foo> (and fails to
398match if nothing is found), while in the second case we can match both C</foo>
399and C</foo/more/to/come>. The following are roughly the same:
400
401 sub (/foo) { 'I match /foo' },
402 sub (/foo/...) {
403 sub (/bar) { 'I match /foo/bar' },
404 sub (/*) { 'I match /foo/{id}' },
405 }
406
407Versus
408
409 sub (/foo...) {
410 sub (~) { 'I match /foo' },
411 sub (/bar) { 'I match /foo/bar' },
412 sub (/*) { 'I match /foo/{id}' },
413 }
414
415You may prefer the latter example should you wish to take advantage of
416subdispatchers to scope common activities. For example:
417
418 sub (/user...) {
419 my $user_rs = $schema->resultset('User');
420 sub (~) { $user_rs },
421 sub (/*) { $user_rs->find($_[1]) },
422 }
423
424You should note the special case path match C<sub (~)> which is only meaningful
425when it is contained in this type of path match. It matches to an empty path.
426
7c03cd61 427=head4 Naming your patch matches
428
65e03df0 429Any C<*>, C<**>, C<*.*>, or C<**.*> match can be followed with C<:name> to make it into a named
7c03cd61 430match, so:
431
432 sub (/*:one/*:two/*:three/*:four) {
433 "I match /1/2/3/4 capturing { one => 1, two => 2, three => 3, four => 4 }"
434 }
435
436 sub (/**.*:allofit) {
437 "I match anything capturing { allofit => \$whole_path }"
438 }
439
582ee8ea 440In the specific case of a simple single-C<*> match, the C<*> may be omitted, to
7c03cd61 441allow you to write:
442
443 sub (/:one/:two/:three/:four) {
444 "I match /1/2/3/4 capturing { one => 1, two => 2, three => 3, four => 4 }"
445 }
446
e060a690 447=head4 C</foo> and C</foo/> are different specs
448
449As you may have noticed with the difference between C<sub(/foo/...)> and
450C<sub(/foo...)>, trailing slashes in path specs are significant. This is
451intentional and necessary to retain the ability to use relative links on
452websites. Let's demonstrate on this link:
453
454 <a href="bar">bar</a>
455
456If the user loads the url C</foo/> and clicks on this link, they will be
457sent to C</foo/bar>. However when they are on the url C</foo> and click this
458link, then they will be sent to C</bar>.
459
460This makes it necessary to be explicit about the trailing slash.
15e679c1 461
81a5b03e 462=head3 Extension matches
463
15dfe701 464 sub (.html) {
465
6a4808bf 466will match .html from the path (assuming the subroutine itself returns
65e03df0 467something, of course). This is normally used for rendering - e.g.:
15dfe701 468
469 sub (.html) {
74afe4b7 470 response_filter { $self->render_html($_[1]) }
15dfe701 471 }
472
b8bd7bd1 473Additionally,
474
475 sub (.*) {
476
6a4808bf 477will match any extension and supplies the extension as a match argument.
b8bd7bd1 478
9b9866ae 479=head3 Query and body parameter matches
480
582ee8ea 481Query and body parameters can be matched via
9b9866ae 482
483 sub (?<param spec>) { # match URI query
484 sub (%<param spec>) { # match body params
485
cb12d2a3 486The body spec will match if the request content is either
487application/x-www-form-urlencoded or multipart/form-data - the latter
c32b7fda 488of which is required for uploads - see below.
9b9866ae 489
65e03df0 490The param spec is elements of one of the following forms:
9b9866ae 491
492 param~ # optional parameter
493 param= # required parameter
494 @param~ # optional multiple parameter
495 @param= # required multiple parameter
eb9e0e25 496 :param~ # optional parameter in hashref
497 :param= # required parameter in hashref
498 :@param~ # optional multiple in hashref
499 :@param= # required multiple in hashref
500 * # include all other parameters in hashref
501 @* # include all other parameters as multiple in hashref
9b9866ae 502
65e03df0 503separated by the C<&> character. The arguments added to the request are
504one per non-C<:>/C<*> parameter (scalar for normal, arrayref for multiple),
505plus if any C<:>/C<*> specs exist a hashref containing those values.
9b9866ae 506
3895385d 507Please note that if you specify a multiple type parameter match, you are
508ensured of getting an arrayref for the value, EVEN if the current incoming
509request has only one value. However if a parameter is specified as single
510and multiple values are found, the last one will be used.
511
65e03df0 512For example to match a C<page> parameter with an optional C<order_by> parameter one
9b9866ae 513would write:
514
515 sub (?page=&order_by~) {
eb9e0e25 516 my ($self, $page, $order_by) = @_;
517 return unless $page =~ /^\d+$/;
518 $page ||= 'id';
9b9866ae 519 response_filter {
520 $_[1]->search_rs({}, $p);
521 }
522 }
523
524to implement paging and ordering against a L<DBIx::Class::ResultSet> object.
525
582ee8ea 526Another example: To get all parameters as a hashref of arrayrefs, write:
eb9e0e25 527
528 sub(?@*) {
529 my ($self, $params) = @_;
530 ...
531
8c4ffad3 532To get two parameters as a hashref, write:
533
534 sub(?:user~&:domain~) {
535 my ($self, $params) = @_; # params contains only 'user' and 'domain' keys
536
537You can also mix these, so:
538
539 sub (?foo=&@bar~&:coffee=&@*) {
540 my ($self, $foo, $bar, $params);
541
582ee8ea 542where C<$bar> is an arrayref (possibly an empty one), and C<$params> contains
543arrayref values for all parameters B<not> mentioned and a scalar value for the
544C<coffee> parameter.
8c4ffad3 545
3895385d 546Note, in the case where you combine arrayref, single parameter and named
547hashref style, the arrayref and single parameters will appear in C<@_> in the
38d5b336 548order you defined them in the protoype, but all hashrefs will merge into a
3895385d 549single C<$params>, as in the example above.
550
1d2f4b67 551=head3 Upload matches
05aafc1a 552
553 sub (*foo=) { # param specifier can be anything valid for query or body
554
555The upload match system functions exactly like a query/body match, except
556that the values returned (if any) are C<Web::Dispatch::Upload> objects.
557
558Note that this match type will succeed in two circumstances where you might
559not expect it to - first, when the field exists but is not an upload field
560and second, when the field exists but the form is not an upload form (i.e.
582ee8ea 561content type C<application/x-www-form-urlencoded> rather than
562C<multipart/form-data>). In either of these cases, what you'll get back is
05aafc1a 563a C<Web::Dispatch::NotAnUpload> object, which will C<die> with an error
564pointing out the problem if you try and use it. To be sure you have a real
565upload object, call
566
567 $upload->is_upload # returns 1 on a valid upload, 0 on a non-upload field
568
569and to get the reason why such an object is not an upload, call
570
571 $upload->reason # returns a reason or '' on a valid upload.
572
573Other than these two methods, the upload object provides the same interface
574as L<Plack::Request::Upload> with the addition of a stringify to the temporary
575filename to make copying it somewhere else easier to handle.
576
81a5b03e 577=head3 Combining matches
578
582ee8ea 579Matches may be combined with the C<+> character - e.g.
15dfe701 580
b8bd7bd1 581 sub (GET + /user/*) {
582
582ee8ea 583to create an AND match. They may also be combined with the C<|> character -
584e.g.
b8bd7bd1 585
586 sub (GET|POST) {
587
582ee8ea 588to create an OR match. Matches can be nested with C<()> - e.g.
b8bd7bd1 589
590 sub ((GET|POST) + /user/*) {
591
582ee8ea 592and negated with C<!> - e.g.
b8bd7bd1 593
594 sub (!/user/foo + /user/*) {
595
582ee8ea 596C<!> binds to the immediate rightmost match specification, so if you want
b8bd7bd1 597to negate a combination you will need to use
598
599 sub ( !(POST|PUT|DELETE) ) {
600
582ee8ea 601and C<|> binds tighter than C<+>, so
b8bd7bd1 602
603 sub ((GET|POST) + /user/*) {
604
605and
606
607 sub (GET|POST + /user/*) {
608
609are equivalent, but
610
1760e999 611 sub ((GET + /admin/...) | (POST + /admin/...)) {
b8bd7bd1 612
613and
614
1760e999 615 sub (GET + /admin/... | POST + /admin/...) {
b8bd7bd1 616
617are not - the latter is equivalent to
618
1760e999 619 sub (GET + (/admin/...|POST) + /admin/...) {
b8bd7bd1 620
3895385d 621which will never match!
b8bd7bd1 622
623=head3 Whitespace
15dfe701 624
65e03df0 625Note that for legibility you are permitted to use whitespace:
15dfe701 626
44db8e76 627 sub (GET + /user/*) {
15dfe701 628
b8bd7bd1 629but it will be ignored. This is because the perl parser strips whitespace
630from subroutine prototypes, so this is equivalent to
631
632 sub (GET+/user/*) {
15dfe701 633
1fc9b979 634=head3 Accessing parameters via C<%_>
635
636If your dispatch specification causes your dispatch subroutine to receive
637a hash reference as its first argument, the contained named parameters
638will be accessible via C<%_>.
639
65e03df0 640This can be used to access your path matches, if they are named:
1fc9b979 641
642 sub (GET + /foo/:path_part) {
643 [ 200,
644 ['Content-type' => 'text/plain'],
645 ["We are in $_{path_part}"],
646 ];
647 }
648
649Or, if your first argument would be a hash reference containing named
650query parameters:
651
652 sub (GET + /foo + ?:some_param=) {
653 [ 200,
654 ['Content-type' => 'text/plain'],
655 ["We received $_{some_param} as parameter"],
656 ];
657 }
658
659Of course this also works when all you are doing is slurping the whole set
660of parameters by their name:
661
662 sub (GET + /foo + ?*) {
663 [ 200,
664 ['Content-type' => 'text/plain'],
665 [exists($_{foo}) ? "Received a foo: $_{foo}" : "No foo!"],
666 ],
667 }
668
65e03df0 669Note that only the first hash reference will be available via C<%_>. If
1fc9b979 670you receive additional hash references, you will need to access them as
671usual.
672
24175cb5 673=head3 Accessing the PSGI env hash
674
3706e2a0 675In some cases you may wish to get the raw PSGI env hash - to do this,
65e03df0 676you can either use a plain sub:
3706e2a0 677
678 sub {
679 my ($env) = @_;
680 ...
681 }
24175cb5 682
65e03df0 683or use the C<PSGI_ENV> constant exported to retrieve it from C<@_>:
c21c9f07 684
3706e2a0 685 sub (GET + /foo + ?some_param=) {
686 my $param = $_[1];
687 my $env = $_[PSGI_ENV];
688 }
c21c9f07 689
3706e2a0 690but note that if you're trying to add a middleware, you should simply use
691Web::Simple's direct support for doing so.
c21c9f07 692
445b3ea0 693=head1 EXPORTED SUBROUTINES
c21c9f07 694
695=head2 response_filter
696
697 response_filter {
698 # Hide errors from the user because we hates them, preciousss
445b3ea0 699 if (ref($_[0]) eq 'ARRAY' && $_[0]->[0] == 500) {
700 $_[0] = [ 200, @{$_[0]}[1..$#{$_[0]}] ];
c21c9f07 701 }
445b3ea0 702 return $_[0];
c21c9f07 703 };
704
705The response_filter subroutine is designed for use inside dispatch subroutines.
706
707It creates and returns a special dispatcher that always matches, and calls
708the block passed to it as a filter on the result of running the rest of the
709current dispatch chain.
710
711Thus the filter above runs further dispatch as normal, but if the result of
712dispatch is a 500 (Internal Server Error) response, changes this to a 200 (OK)
713response without altering the headers or body.
714
715=head2 redispatch_to
716
717 redispatch_to '/other/url';
718
719The redispatch_to subroutine is designed for use inside dispatch subroutines.
720
721It creates and returns a special dispatcher that always matches, and instead
722of continuing dispatch re-delegates it to the start of the dispatch process,
723but with the path of the request altered to the supplied URL.
724
65e03df0 725Thus if you receive a POST to C</some/url> and return a redispatch to
726C</other/url>, the dispatch behaviour will be exactly as if the same POST
727request had been made to C</other/url> instead.
c21c9f07 728
3895385d 729Note, this is not the same as returning an HTTP 3xx redirect as a response;
38d5b336 730rather it is a much more efficient internal process.
3895385d 731
8c4ffad3 732=head1 CHANGES BETWEEN RELEASES
445b3ea0 733
734=head2 Changes between 0.004 and 0.005
735
736=over 4
737
738=item * dispatch {} replaced by declaring a dispatch_request method
739
740dispatch {} has gone away - instead, you write:
741
742 sub dispatch_request {
e4122532 743 my $self = shift;
445b3ea0 744 sub (GET /foo/) { ... },
745 ...
746 }
747
65e03df0 748Note that this method is still B<returning> the dispatch code - just like
749C<dispatch> did.
445b3ea0 750
65e03df0 751Also note that you need the C<< my $self = shift >> since the magic $self
e4122532 752variable went away.
753
754=item * the magic $self variable went away.
755
65e03df0 756Just add C<< my $self = shift; >> while writing your C<< sub dispatch_request { >>
e4122532 757like a normal perl method.
758
445b3ea0 759=item * subdispatch deleted - all dispatchers can now subdispatch
760
761In earlier releases you needed to write:
762
763 subdispatch sub (/foo/...) {
764 ...
765 [
766 sub (GET /bar/) { ... },
767 ...
768 ]
769 }
770
771As of 0.005, you can instead write simply:
772
773 sub (/foo/...) {
774 ...
775 (
776 sub (GET /bar/) { ... },
777 ...
778 )
779 }
8c4ffad3 780
c2150f7d 781=back
782
8c4ffad3 783=head2 Changes since Antiquated Perl
784
785=over 4
786
787=item * filter_response renamed to response_filter
788
789This is a pure rename; a global search and replace should fix it.
790
c21c9f07 791=item * dispatch [] changed to dispatch {}
8c4ffad3 792
793Simply changing
794
795 dispatch [ sub(...) { ... }, ... ];
796
797to
798
799 dispatch { sub(...) { ... }, ... };
800
801should work fine.
802
803=back
804
fb771406 805=head1 DEVELOPMENT HISTORY
806
807Web::Simple was originally written to form part of my Antiquated Perl talk for
808Italian Perl Workshop 2009, but in writing the bloggery example I realised
809that having a bare minimum system for writing web applications that doesn't
810drive me insane was rather nice and decided to spend my attempt at nanowrimo
811for 2009 improving and documenting it to the point where others could use it.
812
58fd1f7f 813The Antiquated Perl talk can be found at L<http://www.shadowcat.co.uk/archive/conference-video/> and the slides are reproduced in this distribution under
814L<Web::Simple::AntiquatedPerl>.
fb771406 815
8c4ffad3 816=head1 COMMUNITY AND SUPPORT
817
818=head2 IRC channel
819
820irc.perl.org #web-simple
821
822=head2 No mailing list yet
823
824Because mst's non-work email is a bombsite so he'd never read it anyway.
825
826=head2 Git repository
827
828Gitweb is on http://git.shadowcat.co.uk/ and the clone URL is:
829
830 git clone git://git.shadowcat.co.uk/catagits/Web-Simple.git
831
832=head1 AUTHOR
833
c2150f7d 834Matt S. Trout (mst) <mst@shadowcat.co.uk>
8c4ffad3 835
836=head1 CONTRIBUTORS
837
48904f80 838Devin Austin (dhoss) <dhoss@cpan.org>
839
840Arthur Axel 'fREW' Schmidt <frioux@gmail.com>
841
c2150f7d 842gregor herrmann (gregoa) <gregoa@debian.org>
8c4ffad3 843
48904f80 844John Napiorkowski (jnap) <jjn1056@yahoo.com>
845
846Josh McMichael <jmcmicha@linus222.gsc.wustl.edu>
847
f42be65c 848Justin Hunter (arcanez) <justin.d.hunter@gmail.com>
48904f80 849
850Kjetil Kjernsmo <kjetil@kjernsmo.net>
851
852markie <markie@nulletch64.dreamhost.com>
853
854Christian Walde (Mithaldu) <walde.christian@googlemail.com>
855
856nperez <nperez@cpan.org>
857
858Robin Edwards <robin.ge@gmail.com>
859
3c39d241 860Andrew Rodland (hobbs) <andrew@cleverdomain.org>
861
c18a76d1 862Robert Sedlacek (phaylon) <r.sedlacek@shadowcat.co.uk>
863
8c4ffad3 864=head1 COPYRIGHT
865
f42be65c 866Copyright (c) 2011 the Web::Simple L</AUTHOR> and L</CONTRIBUTORS>
8c4ffad3 867as listed above.
868
869=head1 LICENSE
870
871This library is free software and may be distributed under the same terms
872as perl itself.
873
3583ca04 874=cut