File Coverage

blib/lib/Web/Simple.pm
Criterion Covered Total %
statement 36 36 100.0
branch 1 2 50.0
condition 2 3 66.6
subroutine 9 9 100.0
pod n/a
total 48 50 96.0


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