5 URL-Based Dispatch
The library allows the creation of two-way mappings between permanent URLs and request-handling procedures.
This library was inspired by the (planet untyped/dispatch) package.
Suppose you are writing a blog application and want pretty URLs for different views of the site.
You would define some URL dispatching rules as follows:
And define your request handlers as follows:
|> (define (list-posts req) `(list-posts))|
|> (define (review-post req p) `(review-post ,p))|
|> (define (review-archive req y m) `(review-archive ,y ,m))|
Now when a request is sent to your application, it will be directed to the appropriate handler:
| (url->request "http://www.chrlsnchrg.com"))|
| (url->request "http://www.chrlsnchrg.com/"))|
| (url->request "http://www.chrlsnchrg.com/archive/1984/10"))|
'(review-archive 1984 10)
| (url->request "http://www.chrlsnchrg.com/contact"))|
You can also generate these pretty URLs from procedure calls:
|> (blog-url list-posts)|
|> (blog-url review-post "Another-Saturday-Night")|
|> (blog-url review-archive 1984 11)|
After mastering the world of blogging software, you decide to put the ubiquitous Add-Two-Numbers.com out of business with Sum.com:
|> (sum-dispatch (url->request "http://www.sum.com/"))|
|> (sum-dispatch (url->request "http://www.sum.com/2"))|
|> (sum-dispatch (url->request "http://www.sum.com/2/3/4"))|
|> (sum-dispatch (url->request "http://www.sum.com/5/10/15/20"))|
|> (sum-url sum empty)|
|> (sum-url sum (list 1))|
|> (sum-url sum (list 2 3 5 7))|
When you use web-server/dispatch with
serve/servlet, you almost always want to use the
#:servlet-regexp argument with the value "" to
capture all top-level requests. However, make sure you don’t include
an else in your rules if you are also serving static files,
or else the filesystem server will never see the requests.
5.2 API Reference
Returns two values: the first is a dispatching function with the contract (-> request? any)
that calls the appropriate dispatch-fun
based on the first dispatch-pattern
that matches the
request’s URL; the second is a URL-generating function with the contract (-> procedure? any/c ... string?)
that generates a URL using dispatch-pattern
for the dispatch-fun
given as its first argument.
If else-fun is left out, one is provided that calls (next-dispatcher) to signal to the Web Server that this
dispatcher does not apply.
| dispatch-pattern|| ||=|| ||()|
| || ||||| ||(string . dispatch-pattern)|
| || ||||| ||(bidi-match-expander ... . dispatch-pattern)|
| || ||||| ||(bidi-match-expander . dispatch-pattern)|
, except returns a third value with the contract (-> request? boolean?)
if the dispatching rules apply to the request and #f
with a #:servlet-regexp
) so that every request is handled by dispatch
5.3 Imperative Dispatch Containers
dispatch-rules is purely functional. This presents a more declarative interface, but inhibits some programming and modularity patterns. Containers provide an imperative overlay atop dispatch-rules.
Defines container-id as a container as well as dispatch-id as its dispatching function and url-id as its URL lookup function.
, but imperatively adds the patterns to the container specified by container-expr
. The new rules are consulted before
any rules already in the container.
5.4 Built-in URL patterns
web-server/dispatch builds in a few useful URL component patterns.
You can create new URL component patterns by defining bi-directional match expanders.
to a bi-directional match expander
is a match expander (defined by define-match-expander
) that is used when parsing URLs
is one used when generating URLs.
Both in-xform and out-xform should use the syntax (xform arg ... id) where the args are
specific to id and compatible with both in-xform and out-xform. id will typically be provided
automatically by dispatch-rules.
When defining new patterns, you may find it useful to use these helper functions:
Binds id to a match expander that expands (id x) to
(? test? (app coerce x)) (i.e., uses test? to determine if the pattern matches and coerce to transform the binding.)
Returns a function that returns #t if coerce would not throw an exception or return #f on its input.