X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FWeb%2FSimple.pm;h=5e38ba8684b1c108ac3a4846b2597d77c9c949bd;hb=74afe4b70dc0f4b5f8de55fb4d17c4863d842c29;hp=c3e5f1933578fbc223972e4a8f88aed9f6ec370c;hpb=b8bd7bd101a70cb5537975e236c1c111d473a009;p=catagits%2FWeb-Simple.git diff --git a/lib/Web/Simple.pm b/lib/Web/Simple.pm index c3e5f19..5e38ba8 100644 --- a/lib/Web/Simple.pm +++ b/lib/Web/Simple.pm @@ -30,12 +30,15 @@ sub _export_into { *{"${app_package}::dispatch"} = sub { $app_package->_setup_dispatcher(@_); }; - *{"${app_package}::filter_response"} = sub (&) { + *{"${app_package}::response_filter"} = sub (&) { $app_package->_construct_response_filter($_[0]); }; *{"${app_package}::redispatch_to"} = sub { $app_package->_construct_redispatch($_[0]); }; + *{"${app_package}::subdispatch"} = sub ($) { + $app_package->_construct_subdispatch($_[0]); + }; *{"${app_package}::default_config"} = sub { $app_package->_setup_default_config(@_); }; @@ -93,9 +96,11 @@ examples and non-CGI deployment, see below. =head1 WHY? -While I originally wrote Web::Simple as part of my Antiquated Perl talk for -Italian Perl Workshop 2009, I've found that having a bare minimum system for -writing web applications that doesn't drive me insane is rather nice. +Web::Simple was originally written to form part of my Antiquated Perl talk for +Italian Perl Workshop 2009, but in writing the bloggery example I realised +that having a bare minimum system for writing web applications that doesn't +drive me insane was rather nice and decided to spend my attempt at nanowrimo +for 2009 improving and documenting it to the point where others could use it. The philosophy of Web::Simple is to keep to an absolute bare minimum, for everything. It is not designed to be used for large scale applications; @@ -143,10 +148,12 @@ It also exports the following subroutines: dispatch [ sub (...) { ... }, ... ]; - filter_response { ... }; + response_filter { ... }; redispatch_to '/somewhere'; + subdispatch sub (...) { ... } + and creates a $self global variable in your application package, so you can use $self in dispatch subs without violating strict (Web::Simple::Application arranges for dispatch subroutines to have the correct $self in scope when @@ -201,8 +208,14 @@ the subroutines passed to it, which then creates your Web::Simple application's dispatcher from these subs. The prototype of the subroutine is expected to be a Web::Simple dispatch specification (see L below for more details), and the body of the -subroutine is the code to execute if the specification matches. See -L below for details on how the Web::Simple dispatch +subroutine is the code to execute if the specification matches. + +Each dispatcher is given the dispatcher constructed from the next element +of the arrayref as its next dispatcher, except for the final element, which +is given the return value of NameOfApplication->_build_final_dispatcher +as its next dispatcher (by default this returns a 500 error response). + +See L below for details on how the Web::Simple dispatch system uses the return values of these subroutines to determine how to continue, alter or abort dispatch. @@ -249,6 +262,26 @@ Thus if you receive a POST to '/some/url' and return a redipstch to '/other/url', the dispatch behaviour will be exactly as if the same POST request had been made to '/other/url' instead. +=head2 subdispatch + + subdispatch sub (/user/*/) { + my $u = $self->user($_[1]); + [ + sub (GET) { $u }, + sub (DELETE) { $u->delete }, + ] + } + +The subdispatch subroutine is designed for use in dispatcher construction. + +It creates a dispatcher which, if it matches, treats its return value not +as a final value but an arrayref of dispatch specifications such as could +be passed to the dispatch subroutine itself. These are turned into a dispatcher +which is then invoked. Any changes the match makes to the request are in +scope for this inner dispatcher only - so if the initial match is a +destructive one like .html the full path will be restored if the +subdispatch fails. + =head1 DISPATCH STRATEGY =head2 Description of the dispatcher object @@ -364,6 +397,22 @@ you can do to match an arbitrary number of parts up to but not including some final part. +Finally, + + sub (/foo/...) { + +will match /foo/ on the beginning of the path -and- strip it, much like +.html strips the extension. This is designed to be used to construct +nested dispatch structures, but can also prove useful for having e.g. an +optional language specification at the start of a path. + +Note that the '...' is a "maybe something here, maybe not" so the above +specification will match like this: + + /foo # no match + /foo/ # match and strip path to '/' + /foo/bar/baz # match and strip path to '/bar/baz' + =head3 Extension matches sub (.html) { @@ -372,7 +421,7 @@ will match and strip .html from the path (assuming the subroutine itself returns something, of course). This is normally used for rendering - e.g. sub (.html) { - filter_response { $self->render_html($_[1]) } + response_filter { $self->render_html($_[1]) } } Additionally, @@ -382,6 +431,50 @@ Additionally, will match any extension and supplies the stripped extension as a match argument. +=head3 Query and body parameter matches + +Query and body parameters can be match via + + sub (?) { # match URI query + sub (%) { # match body params + +The body is only matched if the content type is +application/x-www-form-urlencoded (note this means that Web::Simple does +not yet handle uploads; this will be addressed in a later release). + +The param spec is elements of one of the following forms - + + param~ # optional parameter + param= # required parameter + @param~ # optional multiple parameter + @param= # required multiple parameter + * # include all other parameters + @* # include all other parameters as multiple + +separated by the & character. + +So, to match a page parameter with an optional order_by parameter one +would write: + + sub (?page=&order_by~) { + +Parameters selected are turned into a hashref; in the case of singular +parameters then if multiple values are found the last one is used. In the +case of multiple parameters an arrayref of all values (or an empty arrayref +for a missing optional) is used. The resulting hashref is provided as a +match argument. So we might write something like: + + sub (?page=&order_by~) { + my ($self, $p) = @_; + return unless $p->{page} =~ /^\d+$/; + $p->{order_by} ||= 'id'; + response_filter { + $_[1]->search_rs({}, $p); + } + } + +to implement paging and ordering against a L object. + =head3 Combining matches Matches may be combined with the + character - e.g.