[racket] More consistent approach to web programming?

From: Greg Hendershott (greghendershott at gmail.com)
Date: Wed Oct 6 22:44:50 EDT 2010

I want to share two ideas based on my experience so far with the web
libraries. This isn't cutting edge CS. It's just some practical stuff
about pain points, about how to make it more consistent both
"horizontally" and "vertically", so what you learn starting in one
quadrant is applicable in the other three.

[1] Horizontally. If you start learning the client side, net/url, very
little of what you learn is applicable to the server side. In fact
it's often the opposite. Client is strings, but server is bytes.
Client has one approach to HTTP headers, server has another. The
psychic whiplash is particularly bad if you're switching back and
forth.

(I recognize this is probably the result of two people or teams making
a big contribution at different stages, and they each deserve my
appreciation -- thanks sincerely for what you've done!)

[2] Vertically. xexprs are a great way to deal with HTTP entities:
(tag (attributes) body), nested arbitrarily deeply, quasiquotes, all
that good stuff. But why just entities? HTTP messages have the same
structure, if you consider HTTP headers to be attribute lists for the
entity body. Requests are (method (headers) entity). And responses are
let's say (response (headers) entity).  It would be great to bundle it
all up as one xexpr: (method (headers) entity-xexpr). Now the entire
HTTP message is simply an xexpr, whose entity is in turn an xexpr.

Now everything you learn about using xexprs, you can apply top to
bottom and left to right.

I imagine many people on this list could whip up an xexpr-http.rkt
module pretty quickly, including some functions to get at xexpr parts,
and four functions like send-request and receive-response for the
client, and receive-request and send-response for the server, all
consuming and producing xexprs. As well as helper functions to read
and write entities, automatically transforming common content-types
like text/html, application/xml, application/x-www-form-urlencoded
to/from bytes.

It also helps if you allow these xexprs to have as its body a
procedure (which isn't strictly xexpr? today). So you can do
incremental, "callback" style requests or responses:

`(response ([Status "200" "OK"])
     ,(lambda (out)
        ... a callback ala make/response-incremental ))
-- or ---
`(put ([ ... ])
    ,(lambda (out) ... ))

Of course there's a point where doing TOO much with lists instead of
structs becomes unwieldy. But maybe it's worth pushing it just a bit,
for the sake of xexpr bennies.

Does anyone else see value in this kind of approach?

Is this something where it's considered OK for everyone who wants it,
to code it up themselves?  (Have all of you in fact already done this,
had this supposed epiphany and graduated beyond it years ago? :) )  Or
is worth me putting something like this on GitHub or Planet? Is it
even something to consider for Racket itself someday, considering how
more consistency could make Racket even more appealing for web dev?


Posted on the users mailing list.