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 While I originally wrote Web::Simple as part of my Antiquated Perl talk for
97 Italian Perl Workshop 2009, I've found that having a bare minimum system for
98 writing web applications that doesn't drive me insane is rather nice.
100 The philosophy of Web::Simple is to keep to an absolute bare minimum, for
101 everything. It is not designed to be used for large scale applications;
102 the L<Catalyst> web framework already works very nicely for that and is
103 a far more mature, well supported piece of software.
105 However, if you have an application that only does a couple of things, and
106 want to not have to think about complexities of deployment, then Web::Simple
107 might be just the thing for you.
109 The Antiquated Perl talk can be found at L<http://www.shadowcat.co.uk/archive/conference-video/>.
113 The only public interface the Web::Simple module itself provides is an
116 use Web::Simple 'NameOfApplication';
118 This imports 'strict' and 'warnings FATAL => "all"' into your code as well,
119 so you can skip the usual
124 provided you 'use Web::Simple' at the top of the file. Note that we turn
125 on *fatal* warnings so if you have any warnings at any point from the file
126 that you did 'use Web::Simple' in, then your application will die. This is,
127 so far, considered a feature.
129 Calling the import also makes NameOfApplication isa Web::Simple::Application
130 - i.e. does the equivalent of
133 package NameOfApplication;
134 use base qw(Web::Simple::Application);
137 It also exports the following subroutines:
144 dispatch [ sub (...) { ... }, ... ];
146 filter_response { ... };
148 redispatch_to '/somewhere';
150 and creates a $self global variable in your application package, so you can
151 use $self in dispatch subs without violating strict (Web::Simple::Application
152 arranges for dispatch subroutines to have the correct $self in scope when
157 $INC{"NameOfApplication.pm"} = 'Set by "use Web::Simple;" invocation';
159 so that perl will not attempt to load the application again even if
161 require NameOfApplication;
163 is encountered in other code.
165 =head1 EXPORTED SUBROUTINES
167 =head2 default_config
171 another_key => 'bar',
176 $self->config->{one_key} # 'foo'
178 This creates the default configuration for the application, by creating a
180 sub _default_config {
181 return (one_key => 'foo', another_key => 'bar');
184 in the application namespace when executed. Note that this means that
185 you should only run default_config once - calling it a second time will
186 cause an exception to be thrown.
192 [ 200, [ 'Content-type', 'text/plain' ], [ 'Hello world!' ] ]
195 [ 405, [ 'Content-type', 'text/plain' ], [ 'Method not allowed' ] ]
199 The dispatch subroutine calls NameOfApplication->_setup_dispatcher with
200 the subroutines passed to it, which then creates your Web::Simple
201 application's dispatcher from these subs. The prototype of the subroutine
202 is expected to be a Web::Simple dispatch specification (see
203 L</DISPATCH SPECIFICATIONS> below for more details), and the body of the
204 subroutine is the code to execute if the specification matches. See
205 L</DISPATCH STRATEGY> below for details on how the Web::Simple dispatch
206 system uses the return values of these subroutines to determine how to
207 continue, alter or abort dispatch.
209 Note that _setup_dispatcher creates a
212 return <root dispatcher object here>;
215 method in your class so as with default_config, calling dispatch a second time
216 will result in an exception.
218 =head2 response_filter
221 # Hide errors from the user because we hates them, preciousss
222 if (ref($_[1]) eq 'ARRAY' && $_[1]->[0] == 500) {
223 $_[1] = [ 200, @{$_[1]}[1..$#{$_[1]}] ];
228 The response_filter subroutine is designed for use inside dispatch subroutines.
230 It creates and returns a special dispatcher that always matches, and calls
231 the block passed to it as a filter on the result of running the rest of the
232 current dispatch chain.
234 Thus the filter above runs further dispatch as normal, but if the result of
235 dispatch is a 500 (Internal Server Error) response, changes this to a 200 (OK)
236 response without altering the headers or body.
240 redispatch_to '/other/url';
242 The redispatch_to subroutine is designed for use inside dispatch subroutines.
244 It creates and returns a special dispatcher that always matches, and instead
245 of continuing dispatch re-delegates it to the start of the dispatch process,
246 but with the path of the request altered to the supplied URL.
248 Thus if you receive a POST to '/some/url' and return a redipstch to
249 '/other/url', the dispatch behaviour will be exactly as if the same POST
250 request had been made to '/other/url' instead.
252 =head1 DISPATCH STRATEGY
254 =head2 Description of the dispatcher object
256 Web::Simple::Dispatcher objects have three components:
260 =item * match - an optional test if this dispatcher matches the request
262 =item * call - a routine to call if this dispatcher matches (or has no match)
264 =item * next - the next dispatcher to call
268 When a dispatcher is invoked, it checks its match routine against the
269 request environment. The match routine may provide alterations to the
270 request as a result of matching, and/or arguments for the call routine.
272 If no match routine has been provided then Web::Simple treats this as
273 a success, and supplies the request environment to the call routine as
276 Given a successful match, the call routine is now invoked in list context
277 with any arguments given to the original dispatch, plus any arguments
278 provided by the match result.
280 If this routine returns (), Web::Simple treats this identically to a failure
283 If this routine returns a Web::Simple::Dispatcher, the environment changes
284 are merged into the environment and the new dispatcher's next pointer is
285 set to our next pointer.
287 If this routine returns anything else, that is treated as the end of dispatch
288 and the value is returned.
290 On a failed match, Web::Simple invokes the next dispatcher with the same
291 arguments and request environment passed to the current one. On a successful
292 match that returned a new dispatcher, Web::Simple invokes the new dispatcher
293 with the same arguments but the modified request environment.
295 =head2 How Web::Simple builds dispatcher objects for you
297 In the case of the Web::Simple L</dispatch> export the match is constructed
298 from the subroutine prototype - i.e.
300 sub (<match specification>) {
304 and the 'next' pointer is populated with the next element of the array,
305 expect for the last element, which is given a next that will throw a 500
306 error if none of your dispatchers match. If you want to provide something
307 else as a default, a routine with no match specification always matches, so -
310 [ 404, [ 'Content-type', 'text/plain' ], [ 'Error: Not Found' ] ]
313 will produce a 404 result instead of a 500 by default. You can also override
314 the L<Web::Simple::Application/_build_final_dispatcher> method in your app.
316 Note that the code in the subroutine is executed as a -method- on your
317 application object, so if your match specification provides arguments you
318 should unpack them like so:
320 sub (<match specification>) {
321 my ($self, @args) = @_;
325 =head2 Web::Simple match specifications
327 =head3 Method matches
331 A match specification beginning with a capital letter matches HTTP requests
332 with that request method.
338 A match specification beginning with a / is a path match. In the simplest
339 case it matches a specific path. To match a path with a wildcard part, you
343 $self->handle_user($_[1])
345 This will match /user/<anything> where <anything> does not include a literal
346 / character. The matched part becomes part of the match arguments. You can
347 also match more than one part:
350 my ($self, $user_1, $user_2) = @_;
352 sub (/domain/*/user/*) {
353 my ($self, $domain, $user) = @_;
355 and so on. To match an arbitrary number of parts, use -
359 This will result in an element per /-separated part so matched. Note that
362 sub (/page/**/edit) {
364 to match an arbitrary number of parts up to but not including some final
367 =head3 Extension matches
371 will match and strip .html from the path (assuming the subroutine itself
372 returns something, of course). This is normally used for rendering - e.g.
375 filter_response { $self->render_html($_[1]) }
378 =head3 Combining matches
380 Matches may be combined with the + character - e.g.
384 Note that for legibility you are permitted to use whitespace -
386 sub (GET + /user/*) {
388 but it will be ignored.