Commit | Line | Data |
5c33dda5 |
1 | package Web::Simple; |
2 | |
3 | use strict; |
4 | use warnings FATAL => 'all'; |
5 | |
6 | sub import { |
7 | strict->import; |
8 | warnings->import(FATAL => 'all'); |
9 | warnings->unimport('syntax'); |
10 | warnings->import(FATAL => qw( |
11 | ambiguous bareword digit parenthesis precedence printf |
12 | prototype qw reserved semicolon |
13 | )); |
14 | my ($class, $app_package) = @_; |
15 | $class->_export_into($app_package); |
16 | } |
17 | |
18 | sub _export_into { |
19 | my ($class, $app_package) = @_; |
20 | { |
21 | no strict 'refs'; |
22 | *{"${app_package}::dispatch"} = sub { |
23 | $app_package->_setup_dispatchables(@_); |
24 | }; |
25 | *{"${app_package}::filter_response"} = sub (&) { |
26 | $app_package->_construct_response_filter($_[0]); |
27 | }; |
39119082 |
28 | *{"${app_package}::redispatch_to"} = sub { |
29 | $app_package->_construct_redispatch($_[0]); |
30 | }; |
5c33dda5 |
31 | *{"${app_package}::default_config"} = sub { |
32 | my @defaults = @_; |
33 | *{"${app_package}::_default_config"} = sub { @defaults }; |
34 | }; |
35 | *{"${app_package}::self"} = \${"${app_package}::self"}; |
36 | require Web::Simple::Application; |
37 | unshift(@{"${app_package}::ISA"}, 'Web::Simple::Application'); |
38 | } |
39 | } |
40 | |
7401408e |
41 | =head1 NAME |
42 | |
43 | Web::Simple - A quick and easy way to build simple web applications |
44 | |
45 | =head1 WARNING |
46 | |
47 | This is really quite new. If you're reading this from git, it means it's |
48 | really really new and we're still playing with things. If you're reading |
49 | this on CPAN, it means the stuff that's here we're probably happy with. But |
50 | only probably. So we may have to change stuff. |
51 | |
52 | If we do find we have to change stuff we'll add a section explaining how to |
53 | switch your code across to the new version, and we'll do our best to make it |
54 | as painless as possible because we've got Web::Simple applications too. But |
55 | we can't promise not to change things at all. Not yet. Sorry. |
56 | |
57 | =head1 SYNOPSIS |
58 | |
59 | #!/usr/bin/perl |
60 | |
61 | use Web::Simple 'HelloWorld'; |
62 | |
63 | { |
64 | package HelloWorld; |
65 | |
66 | dispatch [ |
67 | sub (GET) { |
68 | [ 200, [ 'Content-type', 'text/plain' ], [ 'Hello world!' ] ] |
69 | }, |
70 | sub () { |
71 | [ 405, [ 'Content-type', 'text/plain' ], [ 'Method not allowed' ] ] |
72 | } |
73 | ]; |
74 | } |
75 | |
76 | HelloWorld->run_if_script; |
77 | |
78 | If you save this file into your cgi-bin as hello-world.cgi and then visit |
79 | |
80 | http://my.server.name/cgi-bin/hello-world.cgi/ |
81 | |
82 | you'll get the "Hello world!" string output to your browser. For more complex |
83 | examples and non-CGI deployment, see below. |
84 | |
85 | =head1 WHY? |
86 | |
87 | While I originally wrote Web::Simple as part of my Antiquated Perl talk for |
88 | Italian Perl Workshop 2009, I've found that having a bare minimum system for |
89 | writing web applications that doesn't drive me insane is rather nice. |
90 | |
91 | The philosophy of Web::Simple is to keep to an absolute bare minimum, for |
92 | everything. It is not designed to be used for large scale applications; |
93 | the L<Catalyst> web framework already works very nicely for that and is |
94 | a far more mature, well supported piece of software. |
95 | |
96 | However, if you have an application that only does a couple of things, and |
97 | want to not have to think about complexities of deployment, then Web::Simple |
98 | might be just the thing for you. |
99 | |
100 | The Antiquated Perl talk can be found at L<http://www.shadowcat.co.uk/archive/conference-video/>. |
101 | |
102 | =head1 DESCRIPTION |
103 | |
104 | The only public interface the Web::Simple module itself provides is an |
105 | import based one - |
106 | |
107 | use Web::Simple 'NameOfApplication'; |
108 | |
109 | This imports 'strict' and 'warnings FATAL => "all"' into your code as well, |
110 | so you can skip the usual |
111 | |
112 | use strict; |
113 | use warnings; |
114 | |
115 | provided you 'use Web::Simple' at the top of the file. Note that we turn |
116 | on *fatal* warnings so if you have any warnings at any point from the file |
117 | that you did 'use Web::Simple' in, then your application will die. This is, |
118 | so far, considered a feature. |
119 | |
120 | Calling the import also makes NameOfApplication isa Web::Simple::Application |
121 | - i.e. does the equivalent of |
122 | |
123 | { |
124 | package NameOfApplication; |
125 | use base qw(Web::Simple::Application); |
126 | } |
127 | |
128 | It also exports the following subroutines: |
129 | |
130 | default_config( |
131 | key => 'value', |
132 | ... |
133 | ); |
134 | |
135 | dispatch [ sub (...) { ... }, ... ]; |
136 | |
137 | filter_response { ... }; |
138 | |
139 | redispatch_to '/somewhere'; |
140 | |
141 | and creates the $self global variable in your application package, so you can |
142 | use $self in dispatch subs without violating strict (Web::Simple::Application |
143 | arranges for dispatch subroutines to have the correct $self in scope when |
144 | this happens). |
145 | |
146 | =head1 EXPORTED SUBROUTINES |
147 | |
148 | =head2 default_config |
149 | |
150 | default_config( |
151 | one_key => 'foo', |
152 | another_key => 'bar', |
153 | ); |
154 | |
155 | ... |
156 | |
157 | $self->config->{one_key} # 'foo' |
158 | |
159 | This creates the default configuration for the application, by creating a |
160 | |
161 | sub _default_config { |
162 | return (one_key => 'foo', another_key => 'bar'); |
163 | } |
164 | |
165 | in the application namespace when executed. Note that this means that |
166 | you should only run default_config once - a second run will cause a warning |
167 | that you are override the _default_config method in your application, which |
168 | under Web::Simple will of course be fatal. |
169 | |
170 | =head2 dispatch |
171 | |
172 | dispatch [ |
173 | sub (GET) { |
174 | [ 200, [ 'Content-type', 'text/plain' ], [ 'Hello world!' ] ] |
175 | }, |
176 | sub () { |
177 | [ 405, [ 'Content-type', 'text/plain' ], [ 'Method not allowed' ] ] |
178 | } |
179 | ]; |
180 | |
181 | The dispatch subroutine calls NameOfApplication->_setup_dispatchables with |
182 | the subroutines passed to it, which then create's your Web::Simple |
183 | application's dispatcher from these subs. The prototype of the subroutine |
184 | is expected to be a Web::Simple dispatch specification (see |
185 | L</DISPATCH SPECIFICATIONS> below for more details), and the body of the |
186 | subroutine is the code to execute if the specification matches. See |
187 | L</DISPATCH STRATEGY> below for details on how the Web::Simple dispatch |
188 | system uses the return values of these subroutines to determine how to |
189 | continue, alter or abort dispatch. |
190 | |
191 | Note that _setup_dispatchables creates a |
192 | |
193 | sub _dispatchables { |
194 | return (<dispatchable objects here>); |
195 | } |
196 | |
197 | method in your class so as with default_config, calling dispatch a second time |
198 | will result in a fatal warning from your application. |
199 | |
200 | =head2 response_filter |
201 | |
202 | response_filter { |
203 | # Hide errors from the user because we hates them, preciousss |
204 | if (ref($_[1]) eq 'ARRAY' && $_[1]->[0] == 500) { |
205 | $_[1] = [ 200, @{$_[1]}[1..$#{$_[1]}] ]; |
206 | } |
207 | return $_[1]; |
208 | }; |
209 | |
210 | The response_filter subroutine is designed for use inside dispatch subroutines. |
211 | |
212 | It creates and returns a response filter object to the dispatcher, |
213 | encapsulating the block passed to it as the filter routine to call. See |
214 | L</DISPATCH STRATEGY> below for how a response filter affects dispatch. |
215 | |
216 | 1; |
217 | |
5c33dda5 |
218 | 1; |