
On Sat, 23 Jan 2010 21:31:47 +0200, Michael Snoyman
Just as an update, I've made the following changes to my WAI git repo ( http://github.com/snoyberg/wai):
* I removed the RequestBody(Class) bits, and replaced them with "IO (Maybe ByteString)". This is a good example of tradeoffs versus the enumerator approach (see below).
* Are you sure that a strict bytestring is fine here? Can the request body be used to upload large data? If so why not use a lazy one, not (only) for its laziness but for being a list of chunks that fits well into memory caches... * I would call ResponseBody a ResponseReceiver given its use and the sigs of the methods. * Why not use sendLazyByteString in sendFile as a default method, this will fix your "TODO" since I believe the chunk size would be a good one. * Maybe a ResponseReceiver Handle instance could be provided. Since it requires no data type definition and would make an orphan instance elsewhere. Maybe a one for sockets would make sense as well.
* This might just be bikeshedding, but renamed RequestMethod to Method to make names slightly shorter and more consistent.
Good for me
* I implemented Mark's suggestions of adding support for arbitrary request methods and information on HTTP version.
Nice
I've been having some off-list discussions about WAI, and have a few issues to bring up. The first is relatively simple: what do we do about consuming the entire request body? Do we leave that as a task to the application, or should the server ensure that the entire request body is consumed?
Good question, is there something in the HTTP spec about this. I don't think so, and I think it would make sense to give up early if you consider the input as garbage.
Next, I have made the ResponseBodyClass typeclass specifically with the goal of allowing optimizations for lazy bytestrings and sending files. The former seems far-fetched; the latter provides the ability to use a sendfile system call instead of copying the file data into memory. However, in the presence of gzip encoding, how useful is this optimization?
It is useful anyway.
Finally, there is a lot of discussion going on right now about enumerators. The question is whether the WAI protocol should use them. There are two places where they could replace the current offering: request body and response body.
In my opinion, there is no major difference between the Hyena definition of an enumerator and the current response body sendByteString method. The former provides two extra features: there's an accumulating parameter passed around, and a method for indicating early termination. However, the accumulating parameter seems unnecesary to me in general, and when needed we can accomplish the same result with MVars. Early termination seems like something that would be unusual in the response context, and could be handled with exceptions.
IORefs could be sufficient (instead of MVars) but this seems a bit ugly compared to the accumulator. In the other hand sometimes you don't need the accumulator and so just pass a dump unit. If we live in IO yes exceptions could do that. However the point of the Either type is to remind you that you have two cases to handle.
For the request body, there is a significant difference. However, I think that the current approach (called imperative elsewhere) is more in line with how most people would expect to program. At the same time, I believe there is no performance issue going either way, and am open to community input.
Why an imperative approach would be more in line when using a purely functional language? Regards, -- Nicolas Pouillard http://nicolaspouillard.fr