I'm a big fan of declarative programming, that is, describing what I want to happen and letting the computer figure out how to achieve this. Thus, mapping schemes like mapping from URLs or CGI queries to Perl code interest me. I'm searching for a language that has the expressiveness of Perls regular expressions yet works for URLs. Simple regular expressions don't cut it because I want to be largely independent from the order of the CGI parameters. The following are some musings that came to my mind and I'm seeking other prior art, ideas and feedback on and faults with my ideas.
Here's my idea of integrating (CGI) parameter validation and dispatch, with some advantages and some disadvantages:
The basic format is:
url { # some Perl code to be invoked on receiving the URL }
That's pretty abstract, so some more example to flesh it out a bit:
/edit?node=(\w+);... { print "You're trying to edit '$node'"; }; /create?name=(\w+);... { print "You're trying to create '$name' but gave no code to fill it +"; }; /create?name=(\w+);code=(.*) { print "Created as sub $name { $code }"; }; /(.*) { print "Don't know how to handle " . $q->query_path; };
The Perl side would "simply" parse each rule (and the code attached to the rule) into subroutines like this:
# /edit?node=(\w+);... { # print "You're trying to edit '$node'"; # }; sub edit_node { my ($q) = @_; return if ($q->param('node') !~ /^(\w+)$/; my $node = $1; print "You're trying to edit '$node'"; };
The advantages are obvious (to me at least):
The disadvantages I see so far are:
There are currently two other declarative schemes I know of, but I didn't find their documentation too elucidating:
Catalyst has a URL mapping scheme similar to the one I propose below, but it can only map on the query path, not on the query parameters.
Jifty also has a mapping scheme, but I didn't find any documentation besides some uncommented example template on it.
CGI::Application::Dispatch mimics a dispatching scheme that Ruby (on Rails?) has - I've added another column to the table. It has some features that the other systems do not, but also lacks parameter based dispatch.
While formalizing my wishes, I have thought about abstract parameter specifications which don't fit within regex-style "oneliners" but allow me to think about an isomorphic terser syntax. I came up with the following commands and the equivalent formulations in Catalyst and Jifty:
| Abstract name and parameters | Catalyst | Jifty | My own | Ruby/CGI::Application::Dispatch |
|---|---|---|---|---|
| named-path-capture $spec | index-based captures are possible via :Regex('^/(...)/(...)') | ??? | /(?<name1>\w+)/(?<name2>\w+) | /:name1/:name2/ gets turned into { name1 => $value1, name2 => $value2 } |
| optional-path-capture $spec | Index access via :Regex('^/(...)(/...)?') (unconfirmed) | ??? | /(?<name1>\w+)/(?<name2>\w*) | /:name1/:name2? gets turned into { name1 => $value1, name2 => $value2 } (if there is a second path segment) |
| path-matches $re | :Regex('^/.../') | n/a | m!^/.../! | Substring via '...' |
| path-equals $str | :Path('/.../') | |/.../ | /.../ | |
| param-equals $key $val | custom handler | ??? | ;key=val | /.../ |
| param-present $key | custom handler | ??? | ;key=(.*) | n/a |
| param-matches $key $re | custom handler | ??? | ;key=(\d+) | n/a |
| param-default $key $re $val | custom handler | ??? | ;key=(\d+;0) | n/a |
My central question to you is, have you seen anything like this, or can you fill out the missing pieces for Catalyst, Jifty or whatever path matching language you have? Should I pursue this at all or have you followed that path and found it littered with the dead carcasses of those who came before you?
20060720 Added Ruby/CGI::Application::Dispatch information
20060721 Added (slightly modified) Regexp::NamedCaptures syntax for (named) captures of path elements
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |