On Sun, Jan 24, 2010 at 2:38 AM, Nicolas Pouillard
<nicolas.pouillard@gmail.com> wrote:
On Sat, 23 Jan 2010 21:31:47 +0200, Michael Snoyman <
michael@snoyman.com> wrote:
> 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...
Sorry, this is where I should have put in some documentation. The IO (Maybe ByteString) returns chunks of strict bytestring until it encounters the end of the body. If we were to use a lazy bytestring, we would either need lazy I/O or to read everything into memory (which is what we're trying to avoid).
The handler has the prerogative to determine chunk size.
* 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.
Sorry, I added a few more patches since sending this e-mail. I did away with ResponseBody as well, and replaced it with Either FilePath ((ByteString -> IO ()) -> IO ()). This is *very* close to the Hyena version in my opinion, with three differences (I think I've written these elsewhere, so sorry if I'm repeating myself).
1) It provides the option of providing optimized file sending, as per the Happstack sendfile system call. I was concerned at first that we might wish to provide sending multiple files, but I think people will prefer the simplicity that comes without having a typeclass. I'm completely open to revisiting this issue, as I have no strong feelings.
2) There is no "accumulating parameter" as there is with Hyena. In the general case, I don't think it's necesary, and when it is, we can use MVars.
3) There is no built in way to force early termination. I think this is a better approach, since early termination would be an exceptional situation. Forcing the application to check a return value each time would be overhead that would rarely be used, and we can achieve the same effect with an exception.
Sorry for not sending this update earlier, but I only finished at about 2:30 last night. I found it difficult to write coherently.
> * 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.
What do you mean by this? That we don't need to consume that input at all, or that the server should be held responsible for "/dev/null"ing the data?
> 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?