▼ |  | Web: PLT Web Applications

1 | Running Web Servlets
2 | Stateful Servlets
3 | Stateless Servlets
4 | HTTP: Hypertext Transfer Protocol
5 | URL-Based Dispatch
6 | Formlets: Functional Form Abstraction
7 | Templates: Separation of View
8 | Troubleshooting and Tips
| Index

► | 5 | URL-Based Dispatch

5.1 | Using web-server/ dispatch
5.2 | API Reference
5.3 | Built-in URL patterns
5.4 | Extending web-server/ dispatch

On this page:

5.1`` Using web-server/ dispatch
5.2`` API Reference
dispatch-rules
dispatch-case
dispatch-url
serve/ dispatch
5.3`` Built-in URL patterns
number-arg
integer-arg
real-arg
string-arg
symbol-arg
5.4`` Extending web-server/ dispatch
define-bidi-match-expander
bidi-match-going-in?
define-coercion-match-expander
make-coerce-safe?

top← prev up next →

### 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:

> (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]))

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:

> (define (url->request u)
(make-request #"GET" (string->url u) empty
empty #f "1.2.3.4" 80 "4.3.2.1"))

> (blog-dispatch
(url->request "http://www.chrlsnchrg.com"))

(list-posts)

> (blog-dispatch
(url->request "http://www.chrlsnchrg.com/"))

(list-posts)

> (blog-dispatch
(url->request
"http://www.chrlsnchrg.com/posts/Extracurricular-Activity"))

(review-post "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"))

(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:

> (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/"))
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

(dispatch-rules
[dispatch-pattern dispatch-fun]
...
[else else-fun])

(dispatch-rules
[dispatch-pattern dispatch-fun]
...)

> | else-fun |  | : |  | (request? . -> . response/c)

> | dispatch-fun |  | : |  | (request? any/c ... . -> . response/c)

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)

(dispatch-case
[dispatch-pattern dispatch-fun]
...
[else else-fun])

(dispatch-case
[dispatch-pattern dispatch-fun]
...)

> | else-fun |  | : |  | (request? . -> . response/c)

> | dispatch-fun |  | : |  | (request? any/c ... . -> . response/c)

Returns a dispatching function as described by dispatch-rules.

(dispatch-url
[dispatch-pattern dispatch-fun]
...)

| dispatch-fun |  | : |  | (request? any/c ... . -> . response/c)

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

top← prev up next →