racket/collects/web-server/scribblings/web.scrbl
2011-02-03 17:42:33 -05:00

218 lines
7.5 KiB
Racket

#lang scribble/doc
@(require "web-server.rkt")
@title[#:tag "web"]{Web Interaction}
@(require (for-label web-server/servlet/web
web-server/servlet/servlet-structs
web-server/http
racket/list
net/url))
@defmodule[web-server/servlet/web]{The
@racketmodname[web-server/servlet/web] library provides the primary
functions of interest for the servlet developer.
@defproc[(send/back [response can-be-response?])
void?]{
Sends @racket[response] to the client. No continuation is captured, so the servlet is done.
Example:
@racketblock[
(send/back
(response/xexpr
`(html
(body
(h1 "The sum is: "
,(+ first-number
second-number))))))
]
}
@defproc[(send/suspend [make-response (string? . -> . can-be-response?)])
request?]{
Captures the current continuation, stores it with @racket[exp] as the expiration
handler, and binds it to a URL. @racket[make-response] is called with this URL and
is expected to generate a @racket[can-be-response?], which is sent to the client. If the
continuation URL is invoked, the captured continuation is invoked and the request is
returned from this call to @racket[send/suspend].
Example:
@racketblock[
(send/suspend
(lambda (k-url)
(response/xexpr
`(html (head (title "Enter a number"))
(body
(form ([action ,k-url])
"Enter a number: "
(input ([name "number"]))
(input ([type "submit"]))))))))
]
When this form is submitted by the browser, the request will be sent to the URL generated by @racket[send/suspend].
Thus, the request will be ``returned'' from @racket[send/suspend] to the continuation of this call.
}
@defproc[(send/suspend/url [make-response (url? . -> . can-be-response?)])
request?]{
Like @racket[send/suspend] but with a URL struct.
}
@defproc[(send/suspend/dispatch [make-response (((request? . -> . any) . -> . string?) . -> . can-be-response?)])
any]{
Calls @racket[make-response] with a function (@racket[embed/url]) that, when called with a procedure from
@racket[request?] to @racket[any/c] will generate a URL, that when invoked will call
the function with the @racket[request?] object and return the result to the caller of
@racket[send/suspend/dispatch]. Therefore, if you pass @racket[embed/url] the identity function,
@racket[send/suspend/dispatch] devolves into @racket[send/suspend]:
@racketblock[
(define (send/suspend response-generator)
(send/suspend/dispatch
(lambda (embed/url)
(response-generator (embed/url (lambda (x) x))))))
]
Use @racket[send/suspend/dispatch] when there are multiple `logical' continuations of a page.
For example, we could either add to a number or subtract from it:
@racketblock[
(define (count-dot-com i)
(count-dot-com
(send/suspend/dispatch
(lambda (embed/url)
(response/xexpr
`(html
(head (title "Count!"))
(body
(h2 (a ([href
,(embed/url
(lambda (req)
(sub1 i)))])
"-"))
(h1 ,(number->string i))
(h2 (a ([href
,(embed/url
(lambda (req)
(add1 i)))])
"+")))))))))
]
Notice that in this example the result of the handlers are returned to the continuation of @racket[send/suspend/dispatch].
However, it is very common that the return value of @racket[send/suspend/dispatch] is irrelevant in
your application and you may think of it as ``embedding'' value-less callbacks. Here is the same example in this style:
@racketblock[
(define (count-dot-com i)
(send/suspend/dispatch
(lambda (embed/url)
(response/xexpr
`(html
(head (title "Count!"))
(body
(h2 (a ([href
,(embed/url
(lambda (req)
(count-dot-com (sub1 i))))])
"-"))
(h1 ,(number->string i))
(h2 (a ([href
,(embed/url
(lambda (req)
(count-dot-com (add1 i))))])
"+"))))))))
]
}
@defproc[(send/suspend/url/dispatch [make-response (((request? . -> . any) . -> . url?) . -> . can-be-response?)])
any]{
Like @racket[send/suspend/dispatch], but with a URL struct.
}
@defproc[(send/forward [make-response (string? . -> . can-be-response?)])
request?]{
Calls @racket[clear-continuation-table!], then @racket[send/suspend].
Use this if the user can logically go `forward' in your application, but cannot go backward.
}
@defproc[(send/finish [response can-be-response?])
void?]{
Calls @racket[clear-continuation-table!], then @racket[send/back].
Use this if the user is truly `done' with your application. For example, it may be used to display the post-logout page:
@racketblock[
(send/finish
(response/xexpr
`(html (head (title "Logged out"))
(body (p "Thank you for using the services "
"of the Add Two Numbers, Inc.")))))
]
}
@defproc[(redirect/get [#:headers hs (listof header?) empty])
request?]{
Calls @racket[send/suspend] with @racket[redirect-to], passing @racket[hs] as the headers.
This implements the Post-Redirect-Get pattern.
Use this to prevent the @onscreen["Refresh"] button from duplicating effects, such as adding items to a database.
}
@defproc[(redirect/get/forget [#:headers hs (listof header?) empty])
request?]{
Calls @racket[send/forward] with @racket[redirect-to], passing @racket[hs] as the headers.
}
@defthing[current-servlet-continuation-expiration-handler
(parameter/c (or/c false/c
(request? . -> . can-be-response?)))]{
Holds the expiration handler to be used when a continuation
captured in this context is expired, then looked up.
Example:
@racketblock[
(parameterize
([current-servlet-continuation-expiration-handler
(lambda (req)
(response/xexpr
`(html (head (title "Custom Expiration!")))))])
(send/suspend
....))
]
}
@defproc[(clear-continuation-table!)
void?]{
Calls the servlet's manager's @racket[clear-continuation-table!] function. Normally, this deletes all the previously
captured continuations.
}
@defproc[(with-errors-to-browser [send/finish-or-back (can-be-response? . -> . request?)]
[thunk (-> any)])
any]{
Calls @racket[thunk] with an exception handler that generates an HTML error page
and calls @racket[send/finish-or-back].
Example:
@racketblock[
(with-errors-to-browser
send/back
(lambda ()
(/ 1 (get-number (request-number)))))
]
}
@defproc[(adjust-timeout! [t number?])
void?]{
Calls the servlet's manager's @racket[adjust-timeout!] function.
@warning{This is deprecated and will be removed in a future release.}
}
@defproc[(continuation-url? [u url?])
(or/c false/c (list/c number? number? number?))]{
Checks if @racket[u] is a URL that refers to a continuation, if so
returns the instance id, continuation id, and nonce.
}
@defthing[servlet-prompt continuation-prompt-tag?]{The tag used for Web interaction continuation capture.}
}