move key-value match spec documentation
[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
3895385d 241to render a user object to HTML, if there is an incoming URL such as:
242
243 http://myweb.org/user/111.html
244
245This works because as we descend down the dispachers, we first match
246C<sub (.html)>, which adds a C<response_filter> (basically a specialized routine
247that follows the L<Plack::Middleware> specification), and then later we also
248match C<sub (/user/*)> which gets a user and returns that as the response.
582ee8ea 249This user object "bubbles up" through all the wrapping middleware until it hits
3895385d 250the C<response_filter> we defined, after which the return is converted to a
251true html response.
81a5b03e 252
582ee8ea 253However, two types of objects are treated specially - a L<Plack::Component> object
65e03df0 254will have its C<to_app> method called and be used as a dispatcher:
81a5b03e 255
3706e2a0 256 sub dispatch_request {
257 my $self = shift;
258 sub (/static/...) { Plack::App::File->new(...) },
259 ...
81a5b03e 260 }
261
65e03df0 262A L<Plack::Middleware> object will be used as a filter for the rest of the
3706e2a0 263dispatch being returned into:
81a5b03e 264
6af22ff2 265 ## responds to /admin/track_usage AND /admin/delete_accounts
266
3706e2a0 267 sub dispatch_request {
268 my $self = shift;
6af22ff2 269 sub (/admin/**) {
270 Plack::Middleware::Session->new(%opts);
271 },
272 sub (/admin/track_usage) {
273 ## something that needs a session
274 },
275 sub (/admin/delete_accounts) {
276 ## something else that needs a session
277 },
81a5b03e 278 }
279
65e03df0 280Note that this is for the dispatch being B<returned> to, so if you want to
3706e2a0 281provide it inline you need to do:
81a5b03e 282
6af22ff2 283 ## ALSO responds to /admin/track_usage AND /admin/delete_accounts
284
3706e2a0 285 sub dispatch_request {
286 my $self = shift;
3706e2a0 287 sub (/admin/...) {
6af22ff2 288 sub {
289 Plack::Middleware::Session->new(%opts);
290 },
291 sub (/track_usage) {
292 ## something that needs a session
293 },
294 sub (/delete_accounts) {
295 ## something else that needs a session
296 },
3706e2a0 297 }
81a5b03e 298 }
299
3706e2a0 300And that's it - but remember that all this happens recursively - it's
3895385d 301dispatchers all the way down. A URL incoming pattern will run all matching
302dispatchers and then hit all added filters or L<Plack::Middleware>.
3706e2a0 303
81a5b03e 304=head2 Web::Simple match specifications
305
fd0febd7 306Even though the following examples all use subroutine prototypes, an
307alternative to declare a match specification for a given route is to provide a
308L<Dancer>-like key-value list:
309
310 sub dispatch_request {
311 my $self = shift;
312 (
313 '.html' => sub { ... },
314 'GET + /user/*' => sub { ... },
315 ## equivalent to:
316 # sub (.html) { ... },
317 # sub (GET + /user/*) { ... },
318 )
319 }
320
321This can be useful in situations where you are generating a dispatch table
322programmatically, where setting a subroutine's protoype is difficult.
323
81a5b03e 324=head3 Method matches
325
93e30ba3 326 sub (GET) {
15dfe701 327
328A match specification beginning with a capital letter matches HTTP requests
329with that request method.
330
81a5b03e 331=head3 Path matches
332
15dfe701 333 sub (/login) {
334
582ee8ea 335A match specification beginning with a C</> is a path match. In the simplest
15dfe701 336case it matches a specific path. To match a path with a wildcard part, you
337can do:
338
339 sub (/user/*) {
340 $self->handle_user($_[1])
341
342This will match /user/<anything> where <anything> does not include a literal
582ee8ea 343C</> character. The matched part becomes part of the match arguments. You can
15dfe701 344also match more than one part:
345
346 sub (/user/*/*) {
347 my ($self, $user_1, $user_2) = @_;
348
349 sub (/domain/*/user/*) {
350 my ($self, $domain, $user) = @_;
351
65e03df0 352and so on. To match an arbitrary number of parts, use C<**>:
15dfe701 353
354 sub (/page/**) {
1d02a8ae 355 my ($self, $match) = @_;
15dfe701 356
1d02a8ae 357This will result in a single element for the entire match. Note that you can do
15dfe701 358
359 sub (/page/**/edit) {
360
361to match an arbitrary number of parts up to but not including some final
362part.
363
65e03df0 364Note: Since Web::Simple handles a concept of file extensions, C<*> and C<**>
e060a690 365matchers will not by default match things after a final dot, and this
65e03df0 366can be modified by using C<*.*> and C<**.*> in the final position, e.g.:
e060a690 367
368 /one/* matches /one/two.three and captures "two"
369 /one/*.* matches /one/two.three and captures "two.three"
370 /** matches /one/two.three and captures "one/two"
371 /**.* matches /one/two.three and captures "one/two.three"
372
da8429c9 373Finally,
374
375 sub (/foo/...) {
376
65e03df0 377Will match C</foo/> on the beginning of the path B<and> strip it. This is
e060a690 378designed to be used to construct nested dispatch structures, but can also prove
379useful for having e.g. an optional language specification at the start of a
380path.
da8429c9 381
582ee8ea 382Note that the C<...> is a "maybe something here, maybe not" so the above
da8429c9 383specification will match like this:
384
385 /foo # no match
386 /foo/ # match and strip path to '/'
387 /foo/bar/baz # match and strip path to '/bar/baz'
388
e060a690 389Almost the same,
15e679c1 390
e060a690 391 sub (/foo...) {
392
393Will match on C</foo/bar/baz>, but also include C</foo>. Otherwise it
394operates the same way as C</foo/...>.
395
396 /foo # match and strip path to ''
397 /foo/ # match and strip path to '/'
398 /foo/bar/baz # match and strip path to '/bar/baz'
399
400Please note the difference between C<sub(/foo/...)> and C<sub(/foo...)>. In
401the first case, this is expecting to find something after C</foo> (and fails to
402match if nothing is found), while in the second case we can match both C</foo>
403and C</foo/more/to/come>. The following are roughly the same:
404
405 sub (/foo) { 'I match /foo' },
406 sub (/foo/...) {
407 sub (/bar) { 'I match /foo/bar' },
408 sub (/*) { 'I match /foo/{id}' },
409 }
410
411Versus
412
413 sub (/foo...) {
414 sub (~) { 'I match /foo' },
415 sub (/bar) { 'I match /foo/bar' },
416 sub (/*) { 'I match /foo/{id}' },
417 }
418
419You may prefer the latter example should you wish to take advantage of
420subdispatchers to scope common activities. For example:
421
422 sub (/user...) {
423 my $user_rs = $schema->resultset('User');
424 sub (~) { $user_rs },
425 sub (/*) { $user_rs->find($_[1]) },
426 }
427
428You should note the special case path match C<sub (~)> which is only meaningful
429when it is contained in this type of path match. It matches to an empty path.
430
7c03cd61 431=head4 Naming your patch matches
432
65e03df0 433Any C<*>, C<**>, C<*.*>, or C<**.*> match can be followed with C<:name> to make it into a named
7c03cd61 434match, so:
435
436 sub (/*:one/*:two/*:three/*:four) {
437 "I match /1/2/3/4 capturing { one => 1, two => 2, three => 3, four => 4 }"
438 }
439
440 sub (/**.*:allofit) {
441 "I match anything capturing { allofit => \$whole_path }"
442 }
443
582ee8ea 444In the specific case of a simple single-C<*> match, the C<*> may be omitted, to
7c03cd61 445allow you to write:
446
447 sub (/:one/:two/:three/:four) {
448 "I match /1/2/3/4 capturing { one => 1, two => 2, three => 3, four => 4 }"
449 }
450
e060a690 451=head4 C</foo> and C</foo/> are different specs
452
453As you may have noticed with the difference between C<sub(/foo/...)> and
454C<sub(/foo...)>, trailing slashes in path specs are significant. This is
455intentional and necessary to retain the ability to use relative links on
456websites. Let's demonstrate on this link:
457
458 <a href="bar">bar</a>
459
460If the user loads the url C</foo/> and clicks on this link, they will be
461sent to C</foo/bar>. However when they are on the url C</foo> and click this
462link, then they will be sent to C</bar>.
463
464This makes it necessary to be explicit about the trailing slash.
15e679c1 465
81a5b03e 466=head3 Extension matches
467
15dfe701 468 sub (.html) {
469
6a4808bf 470will match .html from the path (assuming the subroutine itself returns
65e03df0 471something, of course). This is normally used for rendering - e.g.:
15dfe701 472
473 sub (.html) {
74afe4b7 474 response_filter { $self->render_html($_[1]) }
15dfe701 475 }
476
b8bd7bd1 477Additionally,
478
479 sub (.*) {
480
6a4808bf 481will match any extension and supplies the extension as a match argument.
b8bd7bd1 482
9b9866ae 483=head3 Query and body parameter matches
484
582ee8ea 485Query and body parameters can be matched via
9b9866ae 486
487 sub (?<param spec>) { # match URI query
488 sub (%<param spec>) { # match body params
489
cb12d2a3 490The body spec will match if the request content is either
491application/x-www-form-urlencoded or multipart/form-data - the latter
c32b7fda 492of which is required for uploads - see below.
9b9866ae 493
65e03df0 494The param spec is elements of one of the following forms:
9b9866ae 495
496 param~ # optional parameter
497 param= # required parameter
498 @param~ # optional multiple parameter
499 @param= # required multiple parameter
eb9e0e25 500 :param~ # optional parameter in hashref
501 :param= # required parameter in hashref
502 :@param~ # optional multiple in hashref
503 :@param= # required multiple in hashref
504 * # include all other parameters in hashref
505 @* # include all other parameters as multiple in hashref
9b9866ae 506
65e03df0 507separated by the C<&> character. The arguments added to the request are
508one per non-C<:>/C<*> parameter (scalar for normal, arrayref for multiple),
509plus if any C<:>/C<*> specs exist a hashref containing those values.
9b9866ae 510
3895385d 511Please note that if you specify a multiple type parameter match, you are
512ensured of getting an arrayref for the value, EVEN if the current incoming
513request has only one value. However if a parameter is specified as single
514and multiple values are found, the last one will be used.
515
65e03df0 516For example to match a C<page> parameter with an optional C<order_by> parameter one
9b9866ae 517would write:
518
519 sub (?page=&order_by~) {
eb9e0e25 520 my ($self, $page, $order_by) = @_;
521 return unless $page =~ /^\d+$/;
522 $page ||= 'id';
9b9866ae 523 response_filter {
524 $_[1]->search_rs({}, $p);
525 }
526 }
527
528to implement paging and ordering against a L<DBIx::Class::ResultSet> object.
529
582ee8ea 530Another example: To get all parameters as a hashref of arrayrefs, write:
eb9e0e25 531
532 sub(?@*) {
533 my ($self, $params) = @_;
534 ...
535
8c4ffad3 536To get two parameters as a hashref, write:
537
538 sub(?:user~&:domain~) {
539 my ($self, $params) = @_; # params contains only 'user' and 'domain' keys
540
541You can also mix these, so:
542
543 sub (?foo=&@bar~&:coffee=&@*) {
544 my ($self, $foo, $bar, $params);
545
582ee8ea 546where C<$bar> is an arrayref (possibly an empty one), and C<$params> contains
547arrayref values for all parameters B<not> mentioned and a scalar value for the
548C<coffee> parameter.
8c4ffad3 549
3895385d 550Note, in the case where you combine arrayref, single parameter and named
551hashref style, the arrayref and single parameters will appear in C<@_> in the
38d5b336 552order you defined them in the protoype, but all hashrefs will merge into a
3895385d 553single C<$params>, as in the example above.
554
1d2f4b67 555=head3 Upload matches
05aafc1a 556
557 sub (*foo=) { # param specifier can be anything valid for query or body
558
559The upload match system functions exactly like a query/body match, except
560that the values returned (if any) are C<Web::Dispatch::Upload> objects.
561
562Note that this match type will succeed in two circumstances where you might
563not expect it to - first, when the field exists but is not an upload field
564and second, when the field exists but the form is not an upload form (i.e.
582ee8ea 565content type C<application/x-www-form-urlencoded> rather than
566C<multipart/form-data>). In either of these cases, what you'll get back is
05aafc1a 567a C<Web::Dispatch::NotAnUpload> object, which will C<die> with an error
568pointing out the problem if you try and use it. To be sure you have a real
569upload object, call
570
571 $upload->is_upload # returns 1 on a valid upload, 0 on a non-upload field
572
573and to get the reason why such an object is not an upload, call
574
575 $upload->reason # returns a reason or '' on a valid upload.
576
577Other than these two methods, the upload object provides the same interface
578as L<Plack::Request::Upload> with the addition of a stringify to the temporary
579filename to make copying it somewhere else easier to handle.
580
81a5b03e 581=head3 Combining matches
582
582ee8ea 583Matches may be combined with the C<+> character - e.g.
15dfe701 584
b8bd7bd1 585 sub (GET + /user/*) {
586
582ee8ea 587to create an AND match. They may also be combined with the C<|> character -
588e.g.
b8bd7bd1 589
590 sub (GET|POST) {
591
582ee8ea 592to create an OR match. Matches can be nested with C<()> - e.g.
b8bd7bd1 593
594 sub ((GET|POST) + /user/*) {
595
582ee8ea 596and negated with C<!> - e.g.
b8bd7bd1 597
598 sub (!/user/foo + /user/*) {
599
582ee8ea 600C<!> binds to the immediate rightmost match specification, so if you want
b8bd7bd1 601to negate a combination you will need to use
602
603 sub ( !(POST|PUT|DELETE) ) {
604
582ee8ea 605and C<|> binds tighter than C<+>, so
b8bd7bd1 606
607 sub ((GET|POST) + /user/*) {
608
609and
610
611 sub (GET|POST + /user/*) {
612
613are equivalent, but
614
1760e999 615 sub ((GET + /admin/...) | (POST + /admin/...)) {
b8bd7bd1 616
617and
618
1760e999 619 sub (GET + /admin/... | POST + /admin/...) {
b8bd7bd1 620
621are not - the latter is equivalent to
622
1760e999 623 sub (GET + (/admin/...|POST) + /admin/...) {
b8bd7bd1 624
3895385d 625which will never match!
b8bd7bd1 626
627=head3 Whitespace
15dfe701 628
65e03df0 629Note that for legibility you are permitted to use whitespace:
15dfe701 630
44db8e76 631 sub (GET + /user/*) {
15dfe701 632
b8bd7bd1 633but it will be ignored. This is because the perl parser strips whitespace
634from subroutine prototypes, so this is equivalent to
635
636 sub (GET+/user/*) {
15dfe701 637
1fc9b979 638=head3 Accessing parameters via C<%_>
639
640If your dispatch specification causes your dispatch subroutine to receive
641a hash reference as its first argument, the contained named parameters
642will be accessible via C<%_>.
643
65e03df0 644This can be used to access your path matches, if they are named:
1fc9b979 645
646 sub (GET + /foo/:path_part) {
647 [ 200,
648 ['Content-type' => 'text/plain'],
649 ["We are in $_{path_part}"],
650 ];
651 }
652
653Or, if your first argument would be a hash reference containing named
654query parameters:
655
656 sub (GET + /foo + ?:some_param=) {
657 [ 200,
658 ['Content-type' => 'text/plain'],
659 ["We received $_{some_param} as parameter"],
660 ];
661 }
662
663Of course this also works when all you are doing is slurping the whole set
664of parameters by their name:
665
666 sub (GET + /foo + ?*) {
667 [ 200,
668 ['Content-type' => 'text/plain'],
669 [exists($_{foo}) ? "Received a foo: $_{foo}" : "No foo!"],
670 ],
671 }
672
65e03df0 673Note that only the first hash reference will be available via C<%_>. If
1fc9b979 674you receive additional hash references, you will need to access them as
675usual.
676
24175cb5 677=head3 Accessing the PSGI env hash
678
3706e2a0 679In some cases you may wish to get the raw PSGI env hash - to do this,
65e03df0 680you can either use a plain sub:
3706e2a0 681
682 sub {
683 my ($env) = @_;
684 ...
685 }
24175cb5 686
65e03df0 687or use the C<PSGI_ENV> constant exported to retrieve it from C<@_>:
c21c9f07 688
3706e2a0 689 sub (GET + /foo + ?some_param=) {
690 my $param = $_[1];
691 my $env = $_[PSGI_ENV];
692 }
c21c9f07 693
3706e2a0 694but note that if you're trying to add a middleware, you should simply use
695Web::Simple's direct support for doing so.
c21c9f07 696
445b3ea0 697=head1 EXPORTED SUBROUTINES
c21c9f07 698
699=head2 response_filter
700
701 response_filter {
702 # Hide errors from the user because we hates them, preciousss
445b3ea0 703 if (ref($_[0]) eq 'ARRAY' && $_[0]->[0] == 500) {
704 $_[0] = [ 200, @{$_[0]}[1..$#{$_[0]}] ];
c21c9f07 705 }
445b3ea0 706 return $_[0];
c21c9f07 707 };
708
709The response_filter subroutine is designed for use inside dispatch subroutines.
710
711It creates and returns a special dispatcher that always matches, and calls
712the block passed to it as a filter on the result of running the rest of the
713current dispatch chain.
714
715Thus the filter above runs further dispatch as normal, but if the result of
716dispatch is a 500 (Internal Server Error) response, changes this to a 200 (OK)
717response without altering the headers or body.
718
719=head2 redispatch_to
720
721 redispatch_to '/other/url';
722
723The redispatch_to subroutine is designed for use inside dispatch subroutines.
724
725It creates and returns a special dispatcher that always matches, and instead
726of continuing dispatch re-delegates it to the start of the dispatch process,
727but with the path of the request altered to the supplied URL.
728
65e03df0 729Thus if you receive a POST to C</some/url> and return a redispatch to
730C</other/url>, the dispatch behaviour will be exactly as if the same POST
731request had been made to C</other/url> instead.
c21c9f07 732
3895385d 733Note, this is not the same as returning an HTTP 3xx redirect as a response;
38d5b336 734rather it is a much more efficient internal process.
3895385d 735
8c4ffad3 736=head1 CHANGES BETWEEN RELEASES
445b3ea0 737
738=head2 Changes between 0.004 and 0.005
739
740=over 4
741
742=item * dispatch {} replaced by declaring a dispatch_request method
743
744dispatch {} has gone away - instead, you write:
745
746 sub dispatch_request {
e4122532 747 my $self = shift;
445b3ea0 748 sub (GET /foo/) { ... },
749 ...
750 }
751
65e03df0 752Note that this method is still B<returning> the dispatch code - just like
753C<dispatch> did.
445b3ea0 754
65e03df0 755Also note that you need the C<< my $self = shift >> since the magic $self
e4122532 756variable went away.
757
758=item * the magic $self variable went away.
759
65e03df0 760Just add C<< my $self = shift; >> while writing your C<< sub dispatch_request { >>
e4122532 761like a normal perl method.
762
445b3ea0 763=item * subdispatch deleted - all dispatchers can now subdispatch
764
765In earlier releases you needed to write:
766
767 subdispatch sub (/foo/...) {
768 ...
769 [
770 sub (GET /bar/) { ... },
771 ...
772 ]
773 }
774
775As of 0.005, you can instead write simply:
776
777 sub (/foo/...) {
778 ...
779 (
780 sub (GET /bar/) { ... },
781 ...
782 )
783 }
8c4ffad3 784
c2150f7d 785=back
786
8c4ffad3 787=head2 Changes since Antiquated Perl
788
789=over 4
790
791=item * filter_response renamed to response_filter
792
793This is a pure rename; a global search and replace should fix it.
794
c21c9f07 795=item * dispatch [] changed to dispatch {}
8c4ffad3 796
797Simply changing
798
799 dispatch [ sub(...) { ... }, ... ];
800
801to
802
803 dispatch { sub(...) { ... }, ... };
804
805should work fine.
806
807=back
808
fb771406 809=head1 DEVELOPMENT HISTORY
810
811Web::Simple was originally written to form part of my Antiquated Perl talk for
812Italian Perl Workshop 2009, but in writing the bloggery example I realised
813that having a bare minimum system for writing web applications that doesn't
814drive me insane was rather nice and decided to spend my attempt at nanowrimo
815for 2009 improving and documenting it to the point where others could use it.
816
58fd1f7f 817The 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
818L<Web::Simple::AntiquatedPerl>.
fb771406 819
8c4ffad3 820=head1 COMMUNITY AND SUPPORT
821
822=head2 IRC channel
823
824irc.perl.org #web-simple
825
826=head2 No mailing list yet
827
828Because mst's non-work email is a bombsite so he'd never read it anyway.
829
830=head2 Git repository
831
832Gitweb is on http://git.shadowcat.co.uk/ and the clone URL is:
833
834 git clone git://git.shadowcat.co.uk/catagits/Web-Simple.git
835
836=head1 AUTHOR
837
c2150f7d 838Matt S. Trout (mst) <mst@shadowcat.co.uk>
8c4ffad3 839
840=head1 CONTRIBUTORS
841
48904f80 842Devin Austin (dhoss) <dhoss@cpan.org>
843
844Arthur Axel 'fREW' Schmidt <frioux@gmail.com>
845
c2150f7d 846gregor herrmann (gregoa) <gregoa@debian.org>
8c4ffad3 847
48904f80 848John Napiorkowski (jnap) <jjn1056@yahoo.com>
849
850Josh McMichael <jmcmicha@linus222.gsc.wustl.edu>
851
f42be65c 852Justin Hunter (arcanez) <justin.d.hunter@gmail.com>
48904f80 853
854Kjetil Kjernsmo <kjetil@kjernsmo.net>
855
856markie <markie@nulletch64.dreamhost.com>
857
858Christian Walde (Mithaldu) <walde.christian@googlemail.com>
859
860nperez <nperez@cpan.org>
861
862Robin Edwards <robin.ge@gmail.com>
863
3c39d241 864Andrew Rodland (hobbs) <andrew@cleverdomain.org>
865
c18a76d1 866Robert Sedlacek (phaylon) <r.sedlacek@shadowcat.co.uk>
867
8c4ffad3 868=head1 COPYRIGHT
869
f42be65c 870Copyright (c) 2011 the Web::Simple L</AUTHOR> and L</CONTRIBUTORS>
8c4ffad3 871as listed above.
872
873=head1 LICENSE
874
875This library is free software and may be distributed under the same terms
876as perl itself.
877
3583ca04 878=cut