racket/collects/web-server/scribblings/page.scrbl
Eli Barzilay d61eb53686 Lots of documentation formatting.
Started as fixing misindented definitions, then more indentations, then
a bunch of similar things (square brackets, huge spaces at end-of-lines,
etc).
2011-08-15 07:50:04 -04:00

98 lines
3.7 KiB
Racket

#lang scribble/doc
@(require "web-server.rkt")
@(require (for-label web-server/servlet
web-server/page
racket/promise
racket/list
xml))
@title[#:tag "page"]{Page: Short-hand for Common Patterns}
@defmodule[web-server/page]
The @web-server provides a simple utility library for building Web applications that consistent mostly of @racket[send/suspend/dispatch]-created pages and request handling.
Most Web applications rely heavily on @racket[send/suspend/dispatch] and typically use the pattern:
@racketblock[
(send/suspend/dispatch
(λ (my-embed/url)
.... (my-embed/url other-page) ....))]
@defform[(page e ...)]{
The @racket[page] macro automates this by expanding @racket[(page e ...)] to a usage of @racket[send/suspend/dispatch] where the syntax parameter @racket[embed/url] is bound to the argument of @racket[send/suspend/dispatch].
}
@defidform[embed/url]{
When used inside @racket[page] syntactically, a rename transformer for the procedure embedding function; otherwise, a syntax error.}
A simple example:
@racketblock[
(page
(response/xexpr
`(html
(body
(a ([href
,(embed/url
(λ (req)
"You clicked!"))])
"Click me")))))]
Similarly, many Web applications make use almost exclusively of
functions that are arguments to @racket[embed/url] and immediately
invoke @racket[send/suspend/dispatch].
@deftogether[[@defform[(lambda/page formals e ...)]
@defform[(define/page (id . formals) e ...)]]]{
The @racket[lambda/page] and @racket[define/page] automate this by
expanding to functions that accept a request as the first argument
(followed by any arguments specified in @racket[formals]) and
immediately wrap their body in @racket[page]. This functions also
cooperate with @racket[get-binding] by binding the request to the
@racket[current-request] parameter.
}
The binding interface of @racketmodname[web-server/http] is powerful,
but subtle to use conveniently due to its protection against hostile
clients.
@deftogether[[
@defparam[current-request req request?]
@defthing[binding-id/c contract?]
@defthing[binding-format/c contract?]
@defproc[(get-binding [id binding-id/c]
[req request? (current-request)]
[#:format format binding-format/c 'string])
(or/c false/c string? bytes? binding?)]
@defproc[(get-bindings [id binding-id/c]
[req request? (current-request)]
[#:format format binding-format/c 'string])
(listof (or/c string? bytes? binding?))]
]]{
The @racket[get-binding](s) interface attempts to resolve this by
providing a powerful interface with convenient defaults.
@racket[get-binding] extracts the first binding of a form input from a
request, while @racket[get-bindings] extracts them all.
They accept a form identifier (@racket[id]) as either a byte string, a
string, or a symbol. In each case, the user input is compared in a
case-sensitive way with the form input.
They accept an optional request argument (@racket[req]) that defaults
to the value of the @racket[current-request] parameter used by
@racket[lambda/page] and @racket[define/page].
Finally, they accept an optional keyword argument (@racket[format])
that specifies the desired return format. The default,
@racket['string], produces a UTF-8 string (or @racket[#f] if the byte
string cannot be converted to UTF-8.) The @racket['bytes] format
always produces the raw byte string. The @racket['file] format
produces the file upload content (or @racket[#f] if the form input was
not an uploaded file.) The @racket['binding] format produces the
binding object.
}