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))|
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.