Saturday, October 01, 2005

Post-Redirect-Get with the PLT web server

Here's a nice idiom easily expressed with the PLT servlet library. Typically in an interactive web application you'd like to respond to form submissions (via "POST") with a page that the user can safely refresh, i.e., a page delivered via "GET". As a result, most people recommend you use what's known as the "Post-Redirect-Get pattern," where the immediate response to a POST is a redirect to an ordinary GET page.

Look how beautifully this is expressed in PLT Scheme:
(define (redirect/get)
(send/suspend
(lambda (k-url)
(redirect-to k-url))))
The send/suspend procedure reifies the current continuation as a web continuation URL. The redirect-to procedure generates a response that redirects the user's browser to the given URL. By combining the two, we simply redirect the user's browser right back to exactly the point in the computation where we are, the only difference being that we've now returned from a "GET" interaction instead of a "POST". Usage looks like:
(define (start initial-request)
(let ([request (send/suspend
(lambda (k-url)
... form ...))])
(redirect/get)
(let ([user (extract-binding/single
'user
(request-bindings request))])
`(html (head (title "Hi"))
(body (p "Hi, " ,user "! Hit refresh!"))))))
(Added to the Scheme Cookbook.)

2 comments:

Anonymous said...

Of course, the inner lambda is not necessary:

(define (redirect/get) (send/suspend redirect-to))

Dave Herman said...

Yes, but people might (wait for it..) miss the point!

(Thank you, thank you, don't forget to tip your waiter...)