4 use warnings FATAL => 'all';
6 sub setup_all_strictures {
8 warnings->import(FATAL => 'all');
11 sub setup_dispatch_strictures {
12 setup_all_strictures();
13 warnings->unimport('syntax');
14 warnings->import(FATAL => qw(
15 ambiguous bareword digit parenthesis precedence printf
16 prototype qw reserved semicolon
21 setup_dispatch_strictures();
22 my ($class, $app_package) = @_;
23 $class->_export_into($app_package);
27 my ($class, $app_package) = @_;
30 *{"${app_package}::dispatch"} = sub {
31 $app_package->_setup_dispatcher(@_);
33 *{"${app_package}::filter_response"} = sub (&) {
34 $app_package->_construct_response_filter($_[0]);
36 *{"${app_package}::redispatch_to"} = sub {
37 $app_package->_construct_redispatch($_[0]);
39 *{"${app_package}::default_config"} = sub {
40 $app_package->_setup_default_config(@_);
42 *{"${app_package}::self"} = \${"${app_package}::self"};
43 require Web::Simple::Application;
44 unshift(@{"${app_package}::ISA"}, 'Web::Simple::Application');
46 (my $name = $app_package) =~ s/::/\//g;
47 $INC{"${name}.pm"} = 'Set by "use Web::Simple;" invocation';
52 Web::Simple - A quick and easy way to build simple web applications
56 This is really quite new. If you're reading this from git, it means it's
57 really really new and we're still playing with things. If you're reading
58 this on CPAN, it means the stuff that's here we're probably happy with. But
59 only probably. So we may have to change stuff.
61 If we do find we have to change stuff we'll add a section explaining how to
62 switch your code across to the new version, and we'll do our best to make it
63 as painless as possible because we've got Web::Simple applications too. But
64 we can't promise not to change things at all. Not yet. Sorry.
70 use Web::Simple 'HelloWorld';
77 [ 200, [ 'Content-type', 'text/plain' ], [ 'Hello world!' ] ]
80 [ 405, [ 'Content-type', 'text/plain' ], [ 'Method not allowed' ] ]
85 HelloWorld->run_if_script;
87 If you save this file into your cgi-bin as hello-world.cgi and then visit
89 http://my.server.name/cgi-bin/hello-world.cgi/
91 you'll get the "Hello world!" string output to your browser. For more complex
92 examples and non-CGI deployment, see below.
96 Web::Simple was originally written to form part of my Antiquated Perl talk for
97 Italian Perl Workshop 2009, but in writing the bloggery example I realised
98 that having a bare minimum system for writing web applications that doesn't
99 drive me insane was rather nice and decided to spend my attempt at nanowrimo
100 for 2009 improving and documenting it to the point where others could use it.
102 The philosophy of Web::Simple is to keep to an absolute bare minimum, for
103 everything. It is not designed to be used for large scale applications;
104 the L<Catalyst> web framework already works very nicely for that and is
105 a far more mature, well supported piece of software.
107 However, if you have an application that only does a couple of things, and
108 want to not have to think about complexities of deployment, then Web::Simple
109 might be just the thing for you.
111 The Antiquated Perl talk can be found at L<http://www.shadowcat.co.uk/archive/conference-video/>.
115 The only public interface the Web::Simple module itself provides is an
118 use Web::Simple 'NameOfApplication';
120 This imports 'strict' and 'warnings FATAL => "all"' into your code as well,
121 so you can skip the usual
126 provided you 'use Web::Simple' at the top of the file. Note that we turn
127 on *fatal* warnings so if you have any warnings at any point from the file
128 that you did 'use Web::Simple' in, then your application will die. This is,
129 so far, considered a feature.
131 Calling the import also makes NameOfApplication isa Web::Simple::Application
132 - i.e. does the equivalent of
135 package NameOfApplication;
136 use base qw(Web::Simple::Application);
139 It also exports the following subroutines:
146 dispatch [ sub (...) { ... }, ... ];
148 filter_response { ... };
150 redispatch_to '/somewhere';
152 and creates a $self global variable in your application package, so you can
153 use $self in dispatch subs without violating strict (Web::Simple::Application
154 arranges for dispatch subroutines to have the correct $self in scope when
159 $INC{"NameOfApplication.pm"} = 'Set by "use Web::Simple;" invocation';
161 so that perl will not attempt to load the application again even if
163 require NameOfApplication;
165 is encountered in other code.
167 =head1 EXPORTED SUBROUTINES
169 =head2 default_config
173 another_key => 'bar',
178 $self->config->{one_key} # 'foo'
180 This creates the default configuration for the application, by creating a
182 sub _default_config {
183 return (one_key => 'foo', another_key => 'bar');
186 in the application namespace when executed. Note that this means that
187 you should only run default_config once - calling it a second time will
188 cause an exception to be thrown.
194 [ 200, [ 'Content-type', 'text/plain' ], [ 'Hello world!' ] ]
197 [ 405, [ 'Content-type', 'text/plain' ], [ 'Method not allowed' ] ]
201 The dispatch subroutine calls NameOfApplication->_setup_dispatcher with
202 the subroutines passed to it, which then creates your Web::Simple
203 application's dispatcher from these subs. The prototype of the subroutine
204 is expected to be a Web::Simple dispatch specification (see
205 L</DISPATCH SPECIFICATIONS> below for more details), and the body of the
206 subroutine is the code to execute if the specification matches. See
207 L</DISPATCH STRATEGY> below for details on how the Web::Simple dispatch
208 system uses the return values of these subroutines to determine how to
209 continue, alter or abort dispatch.
211 Note that _setup_dispatcher creates a
214 return <root dispatcher object here>;
217 method in your class so as with default_config, calling dispatch a second time
218 will result in an exception.
220 =head2 response_filter
223 # Hide errors from the user because we hates them, preciousss
224 if (ref($_[1]) eq 'ARRAY' && $_[1]->[0] == 500) {
225 $_[1] = [ 200, @{$_[1]}[1..$#{$_[1]}] ];
230 The response_filter subroutine is designed for use inside dispatch subroutines.
232 It creates and returns a special dispatcher that always matches, and calls
233 the block passed to it as a filter on the result of running the rest of the
234 current dispatch chain.
236 Thus the filter above runs further dispatch as normal, but if the result of
237 dispatch is a 500 (Internal Server Error) response, changes this to a 200 (OK)
238 response without altering the headers or body.
242 redispatch_to '/other/url';
244 The redispatch_to subroutine is designed for use inside dispatch subroutines.
246 It creates and returns a special dispatcher that always matches, and instead
247 of continuing dispatch re-delegates it to the start of the dispatch process,
248 but with the path of the request altered to the supplied URL.
250 Thus if you receive a POST to '/some/url' and return a redipstch to
251 '/other/url', the dispatch behaviour will be exactly as if the same POST
252 request had been made to '/other/url' instead.
254 =head1 DISPATCH STRATEGY
256 =head2 Description of the dispatcher object
258 Web::Simple::Dispatcher objects have three components:
262 =item * match - an optional test if this dispatcher matches the request
264 =item * call - a routine to call if this dispatcher matches (or has no match)
266 =item * next - the next dispatcher to call
270 When a dispatcher is invoked, it checks its match routine against the
271 request environment. The match routine may provide alterations to the
272 request as a result of matching, and/or arguments for the call routine.
274 If no match routine has been provided then Web::Simple treats this as
275 a success, and supplies the request environment to the call routine as
278 Given a successful match, the call routine is now invoked in list context
279 with any arguments given to the original dispatch, plus any arguments
280 provided by the match result.
282 If this routine returns (), Web::Simple treats this identically to a failure
285 If this routine returns a Web::Simple::Dispatcher, the environment changes
286 are merged into the environment and the new dispatcher's next pointer is
287 set to our next pointer.
289 If this routine returns anything else, that is treated as the end of dispatch
290 and the value is returned.
292 On a failed match, Web::Simple invokes the next dispatcher with the same
293 arguments and request environment passed to the current one. On a successful
294 match that returned a new dispatcher, Web::Simple invokes the new dispatcher
295 with the same arguments but the modified request environment.
297 =head2 How Web::Simple builds dispatcher objects for you
299 In the case of the Web::Simple L</dispatch> export the match is constructed
300 from the subroutine prototype - i.e.
302 sub (<match specification>) {
306 and the 'next' pointer is populated with the next element of the array,
307 expect for the last element, which is given a next that will throw a 500
308 error if none of your dispatchers match. If you want to provide something
309 else as a default, a routine with no match specification always matches, so -
312 [ 404, [ 'Content-type', 'text/plain' ], [ 'Error: Not Found' ] ]
315 will produce a 404 result instead of a 500 by default. You can also override
316 the L<Web::Simple::Application/_build_final_dispatcher> method in your app.
318 Note that the code in the subroutine is executed as a -method- on your
319 application object, so if your match specification provides arguments you
320 should unpack them like so:
322 sub (<match specification>) {
323 my ($self, @args) = @_;
327 =head2 Web::Simple match specifications
329 =head3 Method matches
333 A match specification beginning with a capital letter matches HTTP requests
334 with that request method.
340 A match specification beginning with a / is a path match. In the simplest
341 case it matches a specific path. To match a path with a wildcard part, you
345 $self->handle_user($_[1])
347 This will match /user/<anything> where <anything> does not include a literal
348 / character. The matched part becomes part of the match arguments. You can
349 also match more than one part:
352 my ($self, $user_1, $user_2) = @_;
354 sub (/domain/*/user/*) {
355 my ($self, $domain, $user) = @_;
357 and so on. To match an arbitrary number of parts, use -
361 This will result in an element per /-separated part so matched. Note that
364 sub (/page/**/edit) {
366 to match an arbitrary number of parts up to but not including some final
373 will match /foo/ on the beginning of the path -and- strip it, much like
374 .html strips the extension. This is designed to be used to construct
375 nested dispatch structures, but can also prove useful for having e.g. an
376 optional language specification at the start of a path.
378 Note that the '...' is a "maybe something here, maybe not" so the above
379 specification will match like this:
382 /foo/ # match and strip path to '/'
383 /foo/bar/baz # match and strip path to '/bar/baz'
385 =head3 Extension matches
389 will match and strip .html from the path (assuming the subroutine itself
390 returns something, of course). This is normally used for rendering - e.g.
393 filter_response { $self->render_html($_[1]) }
400 will match any extension and supplies the stripped extension as a match
403 =head3 Combining matches
405 Matches may be combined with the + character - e.g.
407 sub (GET + /user/*) {
409 to create an AND match. They may also be combined withe the | character - e.g.
413 to create an OR match. Matches can be nested with () - e.g.
415 sub ((GET|POST) + /user/*) {
417 and negated with ! - e.g.
419 sub (!/user/foo + /user/*) {
421 ! binds to the immediate rightmost match specification, so if you want
422 to negate a combination you will need to use
424 sub ( !(POST|PUT|DELETE) ) {
426 and | binds tighter than +, so
428 sub ((GET|POST) + /user/*) {
432 sub (GET|POST + /user/*) {
436 sub ((GET + .html) | (POST + .html)) {
440 sub (GET + .html | POST + .html) {
442 are not - the latter is equivalent to
444 sub (GET + (.html|POST) + .html) {
446 which will never match.
450 Note that for legibility you are permitted to use whitespace -
452 sub (GET + /user/*) {
454 but it will be ignored. This is because the perl parser strips whitespace
455 from subroutine prototypes, so this is equivalent to