|(require web-server/dispatch)||package: web-server-lib|
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:
> (define-values (blog-dispatch blog-url) (dispatch-rules [("") list-posts] [("posts" (string-arg)) review-post] [("archive" (integer-arg) (integer-arg)) review-archive] [else list-posts]))
> (define (url->request u) (make-request #"GET" (string->url u) empty (delay empty) #f "22.214.171.124" 80 "126.96.36.199"))
> (blog-dispatch (url->request "http://www.chrlsnchrg.com"))
> (blog-dispatch (url->request "http://www.chrlsnchrg.com/"))
> (blog-dispatch (url->request "http://www.chrlsnchrg.com/posts/Extracurricular-Activity"))
> (blog-dispatch (url->request "http://www.chrlsnchrg.com/archive/1984/10"))
'(review-archive 1984 10)
> (blog-dispatch (url->request "http://www.chrlsnchrg.com/contact"))
> (blog-url list-posts)
> (blog-url review-post "Another-Saturday-Night")
> (blog-url review-archive 1984 11)
> (define-values (sum-dispatch sum-url) (dispatch-rules [((integer-arg) ...) sum] [else (lambda (req) (sum req empty))]))
> (define (sum req is) (apply + is))
> (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.
(dispatch-rules dispatch-clause ... maybe-else-clause)
dispatch-clause = [dispatch-pattern maybe-method dispatch-fun] dispatch-pattern = () | (string . dispatch-pattern) | (bidi-match-expander ... . dispatch-pattern) | (bidi-match-expander . dispatch-pattern) maybe-method =
| #:method method method = pat maybe-else-clause =
| [else else-fun]
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.
The method syntax is used in a match expression to match the request-method part of the incoming request object. However, since HTTP allows methods to use any case, the byte string from request-method is normalized to a lower-case string. Thus, valid patterns are things like: "get", "post", "head", (or "get" "post"), etc.
If method is left out, it assumed to apply to requests without methods and GET methods.
(dispatch-rules+applies dispatch-clause ... maybe-else-clause)
(dispatch-case dispatch-clause ... maybe-else-clause)
(define-container container-id (dispatch-id url-id))
(dispatch-rules! container-expr [dispatch-pattern dispatch-fun] ...)
web-server/dispatch builds in a few useful URL component patterns.
5.5 Extending web-server/dispatch
You can create new URL component patterns by defining bi-directional match expanders.
(define-bidi-match-expander id in-xform out-xform)
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:
(define-coercion-match-expander id test? coerce)