fix silly typo
[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
ca30a017 66Note that you should retain the ->run_if_script even if your app is a
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
102on *fatal* warnings so if you have any warnings at any point from the file
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
3895385d 107the the 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
242route is to provide a Dancer like key-value list:
243
244 sub dispatch_request {
245 my $self = shift;
246 (
247 '.html' => sub { response_filter { $self->render_zoom($_[0]) } },
3da8f8c4 248 '/user/*' => sub { $self->users->get($_[1]) },
20645c5f 249 )
250 }
251
252This can be useful in situations where you are generating a dispatch table
253programmatically, where setting a subroutines protoype is difficult.
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.
263This user object 'bubbles up' through all the wrapping middleware until it hits
264the C<response_filter> we defined, after which the return is converted to a
265true html response.
81a5b03e 266
29c7cff1 267However, two types of objects are treated specially - a C<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
331A match specification beginning with a / is a path match. In the simplest
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
339/ character. The matched part becomes part of the match arguments. You can
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
378Note that the '...' is a "maybe something here, maybe not" so the above
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
440In the specific case of a simple single-* match, the * may be omitted, to
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
481Query and body parameters can be match via
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
3895385d 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
542where $bar is an arrayref (possibly an empty one), and $params contains
65e03df0 543arrayref values for all parameters B<not> mentioned and a scalar value for
8c4ffad3 544the 'coffee' parameter.
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.
561content type "application/x-www-form-urlencoded" rather than
562"multipart/form-data"). In either of these cases, what you'll get back is
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
15dfe701 579Matches may be combined with the + character - e.g.
580
b8bd7bd1 581 sub (GET + /user/*) {
582
583to create an AND match. They may also be combined withe the | character - e.g.
584
585 sub (GET|POST) {
586
587to create an OR match. Matches can be nested with () - e.g.
588
589 sub ((GET|POST) + /user/*) {
590
591and negated with ! - e.g.
592
593 sub (!/user/foo + /user/*) {
594
595! binds to the immediate rightmost match specification, so if you want
596to negate a combination you will need to use
597
598 sub ( !(POST|PUT|DELETE) ) {
599
600and | binds tighter than +, so
601
602 sub ((GET|POST) + /user/*) {
603
604and
605
606 sub (GET|POST + /user/*) {
607
608are equivalent, but
609
1760e999 610 sub ((GET + /admin/...) | (POST + /admin/...)) {
b8bd7bd1 611
612and
613
1760e999 614 sub (GET + /admin/... | POST + /admin/...) {
b8bd7bd1 615
616are not - the latter is equivalent to
617
1760e999 618 sub (GET + (/admin/...|POST) + /admin/...) {
b8bd7bd1 619
3895385d 620which will never match!
b8bd7bd1 621
622=head3 Whitespace
15dfe701 623
65e03df0 624Note that for legibility you are permitted to use whitespace:
15dfe701 625
44db8e76 626 sub (GET + /user/*) {
15dfe701 627
b8bd7bd1 628but it will be ignored. This is because the perl parser strips whitespace
629from subroutine prototypes, so this is equivalent to
630
631 sub (GET+/user/*) {
15dfe701 632
1fc9b979 633=head3 Accessing parameters via C<%_>
634
635If your dispatch specification causes your dispatch subroutine to receive
636a hash reference as its first argument, the contained named parameters
637will be accessible via C<%_>.
638
65e03df0 639This can be used to access your path matches, if they are named:
1fc9b979 640
641 sub (GET + /foo/:path_part) {
642 [ 200,
643 ['Content-type' => 'text/plain'],
644 ["We are in $_{path_part}"],
645 ];
646 }
647
648Or, if your first argument would be a hash reference containing named
649query parameters:
650
651 sub (GET + /foo + ?:some_param=) {
652 [ 200,
653 ['Content-type' => 'text/plain'],
654 ["We received $_{some_param} as parameter"],
655 ];
656 }
657
658Of course this also works when all you are doing is slurping the whole set
659of parameters by their name:
660
661 sub (GET + /foo + ?*) {
662 [ 200,
663 ['Content-type' => 'text/plain'],
664 [exists($_{foo}) ? "Received a foo: $_{foo}" : "No foo!"],
665 ],
666 }
667
65e03df0 668Note that only the first hash reference will be available via C<%_>. If
1fc9b979 669you receive additional hash references, you will need to access them as
670usual.
671
24175cb5 672=head3 Accessing the PSGI env hash
673
3706e2a0 674In some cases you may wish to get the raw PSGI env hash - to do this,
65e03df0 675you can either use a plain sub:
3706e2a0 676
677 sub {
678 my ($env) = @_;
679 ...
680 }
24175cb5 681
65e03df0 682or use the C<PSGI_ENV> constant exported to retrieve it from C<@_>:
c21c9f07 683
3706e2a0 684 sub (GET + /foo + ?some_param=) {
685 my $param = $_[1];
686 my $env = $_[PSGI_ENV];
687 }
c21c9f07 688
3706e2a0 689but note that if you're trying to add a middleware, you should simply use
690Web::Simple's direct support for doing so.
c21c9f07 691
445b3ea0 692=head1 EXPORTED SUBROUTINES
c21c9f07 693
694=head2 response_filter
695
696 response_filter {
697 # Hide errors from the user because we hates them, preciousss
445b3ea0 698 if (ref($_[0]) eq 'ARRAY' && $_[0]->[0] == 500) {
699 $_[0] = [ 200, @{$_[0]}[1..$#{$_[0]}] ];
c21c9f07 700 }
445b3ea0 701 return $_[0];
c21c9f07 702 };
703
704The response_filter subroutine is designed for use inside dispatch subroutines.
705
706It creates and returns a special dispatcher that always matches, and calls
707the block passed to it as a filter on the result of running the rest of the
708current dispatch chain.
709
710Thus the filter above runs further dispatch as normal, but if the result of
711dispatch is a 500 (Internal Server Error) response, changes this to a 200 (OK)
712response without altering the headers or body.
713
714=head2 redispatch_to
715
716 redispatch_to '/other/url';
717
718The redispatch_to subroutine is designed for use inside dispatch subroutines.
719
720It creates and returns a special dispatcher that always matches, and instead
721of continuing dispatch re-delegates it to the start of the dispatch process,
722but with the path of the request altered to the supplied URL.
723
65e03df0 724Thus if you receive a POST to C</some/url> and return a redispatch to
725C</other/url>, the dispatch behaviour will be exactly as if the same POST
726request had been made to C</other/url> instead.
c21c9f07 727
3895385d 728Note, this is not the same as returning an HTTP 3xx redirect as a response;
38d5b336 729rather it is a much more efficient internal process.
3895385d 730
8c4ffad3 731=head1 CHANGES BETWEEN RELEASES
445b3ea0 732
733=head2 Changes between 0.004 and 0.005
734
735=over 4
736
737=item * dispatch {} replaced by declaring a dispatch_request method
738
739dispatch {} has gone away - instead, you write:
740
741 sub dispatch_request {
e4122532 742 my $self = shift;
445b3ea0 743 sub (GET /foo/) { ... },
744 ...
745 }
746
65e03df0 747Note that this method is still B<returning> the dispatch code - just like
748C<dispatch> did.
445b3ea0 749
65e03df0 750Also note that you need the C<< my $self = shift >> since the magic $self
e4122532 751variable went away.
752
753=item * the magic $self variable went away.
754
65e03df0 755Just add C<< my $self = shift; >> while writing your C<< sub dispatch_request { >>
e4122532 756like a normal perl method.
757
445b3ea0 758=item * subdispatch deleted - all dispatchers can now subdispatch
759
760In earlier releases you needed to write:
761
762 subdispatch sub (/foo/...) {
763 ...
764 [
765 sub (GET /bar/) { ... },
766 ...
767 ]
768 }
769
770As of 0.005, you can instead write simply:
771
772 sub (/foo/...) {
773 ...
774 (
775 sub (GET /bar/) { ... },
776 ...
777 )
778 }
8c4ffad3 779
c2150f7d 780=back
781
8c4ffad3 782=head2 Changes since Antiquated Perl
783
784=over 4
785
786=item * filter_response renamed to response_filter
787
788This is a pure rename; a global search and replace should fix it.
789
c21c9f07 790=item * dispatch [] changed to dispatch {}
8c4ffad3 791
792Simply changing
793
794 dispatch [ sub(...) { ... }, ... ];
795
796to
797
798 dispatch { sub(...) { ... }, ... };
799
800should work fine.
801
802=back
803
fb771406 804=head1 DEVELOPMENT HISTORY
805
806Web::Simple was originally written to form part of my Antiquated Perl talk for
807Italian Perl Workshop 2009, but in writing the bloggery example I realised
808that having a bare minimum system for writing web applications that doesn't
809drive me insane was rather nice and decided to spend my attempt at nanowrimo
810for 2009 improving and documenting it to the point where others could use it.
811
58fd1f7f 812The 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
813L<Web::Simple::AntiquatedPerl>.
fb771406 814
8c4ffad3 815=head1 COMMUNITY AND SUPPORT
816
817=head2 IRC channel
818
819irc.perl.org #web-simple
820
821=head2 No mailing list yet
822
823Because mst's non-work email is a bombsite so he'd never read it anyway.
824
825=head2 Git repository
826
827Gitweb is on http://git.shadowcat.co.uk/ and the clone URL is:
828
829 git clone git://git.shadowcat.co.uk/catagits/Web-Simple.git
830
831=head1 AUTHOR
832
c2150f7d 833Matt S. Trout (mst) <mst@shadowcat.co.uk>
8c4ffad3 834
835=head1 CONTRIBUTORS
836
48904f80 837Devin Austin (dhoss) <dhoss@cpan.org>
838
839Arthur Axel 'fREW' Schmidt <frioux@gmail.com>
840
c2150f7d 841gregor herrmann (gregoa) <gregoa@debian.org>
8c4ffad3 842
48904f80 843John Napiorkowski (jnap) <jjn1056@yahoo.com>
844
845Josh McMichael <jmcmicha@linus222.gsc.wustl.edu>
846
f42be65c 847Justin Hunter (arcanez) <justin.d.hunter@gmail.com>
48904f80 848
849Kjetil Kjernsmo <kjetil@kjernsmo.net>
850
851markie <markie@nulletch64.dreamhost.com>
852
853Christian Walde (Mithaldu) <walde.christian@googlemail.com>
854
855nperez <nperez@cpan.org>
856
857Robin Edwards <robin.ge@gmail.com>
858
3c39d241 859Andrew Rodland (hobbs) <andrew@cleverdomain.org>
860
c18a76d1 861Robert Sedlacek (phaylon) <r.sedlacek@shadowcat.co.uk>
862
8c4ffad3 863=head1 COPYRIGHT
864
f42be65c 865Copyright (c) 2011 the Web::Simple L</AUTHOR> and L</CONTRIBUTORS>
8c4ffad3 866as listed above.
867
868=head1 LICENSE
869
870This library is free software and may be distributed under the same terms
871as perl itself.
872
3583ca04 873=cut