5 URL-Based Dispatch
(require web-server/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.
5.1 Using web-server/dispatch
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:
| |||
| |||
(list-posts) | |||
| |||
(list-posts) | |||
| |||
(review-post "Extracurricular-Activity") | |||
| |||
(review-archive 1984 10) | |||
| |||
(list-posts) |
You can also generate these pretty URLs from procedure calls:
> (blog-url list-posts) |
"/" |
> (blog-url review-post "Another-Saturday-Night") |
"/posts/Another-Saturday-Night" |
> (blog-url review-archive 1984 11) |
"/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/")) | ||||
0 | ||||
> (sum-dispatch (url->request "http://www.sum.com/2")) | ||||
2 | ||||
> (sum-dispatch (url->request "http://www.sum.com/2/3/4")) | ||||
9 | ||||
> (sum-dispatch (url->request "http://www.sum.com/5/10/15/20")) | ||||
50 | ||||
> (sum-url sum empty) | ||||
"/" | ||||
> (sum-url sum (list 1)) | ||||
"/1" | ||||
> (sum-url sum (list 2 3 5 7)) | ||||
"/2/3/5/7" |
5.2 API Reference
| ||||||||||||
| ||||||||||||
|
Returns two values: the first is a dispatching function with the contract (-> request? response/c) 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) |
| ||||||||||||
| ||||||||||||
|
Returns a dispatching function as described by dispatch-rules.
| ||||||
|
Returns a URL-generating function as described by dispatch-rules.
(serve/dispatch dispatch) → void |
dispatch : (request? . -> . response/c) |
Calls serve/servlet with appropriate arguments so that every request is handled by dispatch.
5.3 Built-in URL patterns
web-server/dispatch builds in a few useful URL component patterns.
(number-arg) |
A bi-directional match expander that parses a number? from the URL and generates a URL with a number’s encoding as a string.
(integer-arg) |
A bi-directional match expander that parses a integer? from the URL and generates a URL with a integer’s encoding as a string.
(real-arg) |
A bi-directional match expander that parses a real? from the URL and generates a URL with a real’s encoding as a string.
(string-arg) |
A bi-directional match expander that parses a string? from the URL and generates a URL containing the string.
(symbol-arg) |
A bi-directional match expander that parses a symbol? from the URL and generates a URL with a symbol’s encoding as a string.
5.4 Extending web-server/dispatch
(require web-server/dispatch/extend) |
You can create new URL component patterns by defining bi-directional match expanders.
(define-bidi-match-expander id in-xform out-xform) |
Binds id to a bi-directional match expander where in-xform is a match expander (defined by define-match-expander) that is used when parsing URLs and out-xform is one used when generating URLs.
bidi-match-going-in? |
A syntax parameter used by bi-directional match expanders to determine if a URL is being parsed or generated.
When defining new patterns, you may find it useful to use these helper functions:
(define-coercion-match-expander id test? coerce) |
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.)
(make-coerce-safe? coerce) → (any/c . -> . boolean?) |
coerce : (any/c . -> . any/c) |
Returns a function that returns #t if coerce would not throw an exception or return #f on its input.
Examples: |
> (define string->number? (make-coerce-safe? string->number)) |
> (string->number? "1") |
#t |
> (string->number? "1.2") |
#t |
> (string->number? "+inf.0") |
#t |
> (string->number? "one") |
#f |