[plt-scheme] Are web-server continuations "safe"?

From: Dave Gurnell (islandthreeband at gmail.com)
Date: Tue Mar 4 13:40:38 EST 2008

I've had a number of requests to talk about the bookmarkable URL  
package on-list. The library, which is currently unnamed, is basically  
the "dispatcher" and "request pipeline" parts from Noel's ICFP 2007  
paper:

     http://www.untyped.com/downloads/icfp068-welsh.pdf

Here's a little more detail. I shall refer to the nameless library as  
"Dispatch" for the purposes of this email. Dispatch has three main  
functions:



The first function is to provide a mapping from bookmarkable URLs to  
"controller" procedures that handle requests.

Suppose I have a blog. Two things people like to do with blogs are:  
view a list of posts and view a single post. I want to create  
bookmarkable URLs for these things. In a Ruby-on-Rails aesthetic these  
would be something like:

     http://www.example.com/             for the index
     http://www.example.com/posts/slug   for the post

For convenience I want to write separate procedures to handle requests  
to these URLs:

   list-posts  : request -> response
   review-post : request string -> response

(the string is the post slug).

Dispatch provides a really quick way to set up mappings from URLs to  
controllers. First I write a "site" declaration in a module called  
site.ss:

   #lang scheme/base

   (define-site blog
     ([(url "/")                       list-posts]
      [(url "/posts/" (string-arg))    review-post]))

then I write my controllers in, say, controller.ss:

   #lang scheme/base

   (require (file "site.ss"))

   (define-controller (list-posts request)
     ...)

   (define-controller (review-posts request slug)
     ...)

Finally, I write my servlet and use a procedure to dispatch the  
request to the relevant controller:

   #lang scheme/base

   (require (file "site.ss")
            (file "controller.ss"))

   (define (start initial-request)
     (dispatch initial-request blog))

The dispatch function runs through the URL rules in the site until it  
finds one that matches the request. Once it's there it calls the  
controller.



The second function of Dispatch is to provide a reverse mapping from  
controllers to URLs:

One of the beauties of continuation-oriented web programming is that  
you don't have to worry about URL structures. I want the same solution  
for my permanent bookmarkable URLs. Dispatch provides a procedure,  
controller-url, that generates a URL from a controller and a list of  
arguments:

     controller-url : controller any ... -> string

     (controller-url review-post "hello-world") -> "/posts/hello-world"

You don't get the flexibility of state-passing that you get with  
continuations, but you do get a nice, friendly, bookmarkable URL.



The third function of Dispatch is to get around an irritating problem  
I've had in the past:

I like writing web apps in MVC style. I typically divide my apps into  
three sets of modules: one set for the model, one set for the view,  
and one set for the controllers. The model is usually a separate  
entity, but the view and the controller tend to refer to one another a  
lot. I get fed up chasing cyclic require bugs very quickly.

Some people might rightly say "use units", but I find units to be  
quite complicated for this kind of thing. They require the creation of  
extra signatures that muddy the waters a little, and they don't  
integrate properly with DrScheme's "Check Syntax" view, which I tend  
to use heavily.

Dispatch solves this problem with a quick and dirty bit of mutation.  
All the actual definitions are provided by define-site in site.ss: the  
define-controller macro simply updates the relevant definition with  
the body procedure. You can require "site.ss" all over your software  
and call any controller directly, by continuation or via controller-url.



There are another couple of features too. Ones that spring to mind:
- the arguments in URLs can generate controller arguments of arbitrary  
types;
- and there's built-in support for the "request pipelines" described  
in the ICFP paper.



Anyway, Dispatch is pretty much ready for release. I really just need  
a witty name and a little more documentation. I'm going to have a few  
hours on the train over the next couple of days so hopefully I'll make  
some headway and get it out this week.



Cheers,

-- Dave
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20080304/9c137172/attachment.html>

Posted on the users mailing list.