[Haskell-cafe] PROPOSAL: Web application interface
michael at snoyman.com
Sun Jan 17 11:01:03 EST 2010
Following up on the previous thread, I've started a github project for some
ideas of a web application interface. It's borrowing from both Hyena and
Hack, with a few of its own ideas. The project is available at
http://github.com/snoyberg/wai, and the Network.Wai module is available at
http://github.com/snoyberg/wai/blob/master/Network/Wai.hs. The repository
also includes a port of hack-handler-simpleserver, and an incredibly simple
webapp to demonstrate usage. I intend to make the demonstration slightly
more sophisticated. Finally, the repository is now yet cabalized.
I consider this currently to be a straw-man proposal, intended to highlight
the issues of contention that may arise. It would be wonderful is we could
get the major players in the Haskell web space to get behind a single WAI.
The entire Network.Wai module right now weighs in at only 74 lines, so I do
not consider this to be a heavy-weight proposal. Here as some design notes:
- Most important point: RequestBody and ResponseBody. I will explain
- I've renamed "Env" in Hack and "Environment" in Hyena to "Request."
This seems more consistent with other technologies out there. However, I
have no feelings on this subject at all, and can easily bend to public
- I've stuck with UrlScheme from Hack, while Hyena called it protocol.
Similar, the RequestMethod constructors are ALLCAPS like Hack, unlike
Hyena's Uppercase. Once again, no strong feelings.
- I've sided with Hyena as far as making all representations in
ByteString. Current exception is remoteHost, which is a Hack-only variable
in any event.
- Instead of representing the response as a tuple ala Hyena, created a
data type like Hack.
- The only dependency for this module is bytestring. It might be tempting
to represent RequestBody and ResponseBody with a ReaderT IO monad, but this
would introduce a dependency on either mtl or transformers, which I would
consider a Very Bad Idea.
The main complaint against Hack is its lack of an enumerator interface for
the request and response body. However, this simply words the complaint
incorrectly; I don't think anyone is married to the need of an enumerator.
Rather, we want to be able to efficiently handle arbitrarily lengthed
content in constant space, without necesarily resorting to
unsafeInterleaveIO (ie, lazy I/O).
There are a number of issues with left-fold enumerators IMO. It is basically
promoting an inversion of control. This may be often times valuable.
However, to make this the *only* interface precludes other use cases. The
most basic one I ran into was wanting to interleave with read processes. I
do not mean to say that it's impossible to interleave reads in such a
manner, but I think it's more natural in the approach advocated by wai.
I consider RequestBody and ResponseBody to be mirroring the CGI protocol.
Essentially, each handler (CGI, simpleserver, FastCGI, happstack server,
etc) will define data types which instanciate RequestBodyClass and
ResponseBodyClass. RequestBodyClass provides a single method,
receiveByteString, to extract a chunk of data from the request body.
ResponseBodyClass provides (currently) three methods, for sending strict
bytestrings, lazy bytestrings, and files. While default implementations are
provided for the last two based on the first, implementations can provide
more efficient versions of them if desired. For example, sendFile might be
replaced by a system call to sendfile.
Let me know your thoughts. I'm purposely leaving out many of my reasons for
the decisions I've made for brevity, since this e-mail is long enough as is.
I'm happy to answer any questions as to why I went in a certain direction.
It's also possible that I simply overlooked a detail.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Haskell-Cafe