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