<div dir="ltr"><br><br><div class="gmail_quote">On Sun, Jan 24, 2010 at 2:38 AM, Nicolas Pouillard <span dir="ltr">&lt;<a href="mailto:nicolas.pouillard@gmail.com">nicolas.pouillard@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="im">On Sat, 23 Jan 2010 21:31:47 +0200, Michael Snoyman &lt;<a href="mailto:michael@snoyman.com">michael@snoyman.com</a>&gt; wrote:<br>
&gt; Just as an update, I&#39;ve made the following changes to my WAI git repo (<br>
&gt; <a href="http://github.com/snoyberg/wai" target="_blank">http://github.com/snoyberg/wai</a>):<br>
&gt;<br>
&gt; * I removed the RequestBody(Class) bits, and replaced them with &quot;IO (Maybe<br>
&gt; ByteString)&quot;. This is a good example of tradeoffs versus the enumerator<br>
&gt; approach (see below).<br>
<br>
</div>* Are you sure that a strict bytestring is fine here? Can the request body<br>
  be used to upload large data? If so why not use a lazy one, not (only)<br>
  for its laziness but for being a list of chunks that fits well into memory<br>
  caches...<br>
<br></blockquote><div>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&#39;re trying to avoid).<br>
<br>The handler has the prerogative to determine chunk size.<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
* I would call ResponseBody a ResponseReceiver given its use and the sigs<br>
  of the methods.<br>
<br>
* Why not use sendLazyByteString in sendFile as a default method, this<br>
  will fix your &quot;TODO&quot; since I believe the chunk size would be a good one.<br>
<br>
* Maybe a ResponseReceiver Handle instance could be provided. Since it<br>
  requires no data type definition and would make an orphan instance elsewhere.<br>
  Maybe a one for sockets would make sense as well.<br>
<div class="im"><br></div></blockquote><div>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 -&gt; IO ()) -&gt; IO ()). This is *very* close to the Hyena version in my opinion, with three differences (I think I&#39;ve written these elsewhere, so sorry if I&#39;m repeating myself).<br>
<br>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&#39;m completely open to revisiting this issue, as I have no strong feelings.<br>
2) There is no &quot;accumulating parameter&quot; as there is with Hyena. In the general case, I don&#39;t think it&#39;s necesary, and when it is, we can use MVars.<br>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.<br>
<br>Sorry for not sending this update earlier, but I only finished at about 2:30 last night. I found it difficult to write coherently.<br><br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="im">
&gt; * This might just be bikeshedding, but renamed RequestMethod to Method to<br>
&gt; make names slightly shorter and more consistent.<br>
<br>
</div>Good for me<br>
<div class="im"><br>
&gt; * I implemented Mark&#39;s suggestions of adding support for arbitrary request<br>
&gt; methods and information on HTTP version.<br>
<br>
</div>Nice<br>
<div class="im"><br>
&gt; I&#39;ve been having some off-list discussions about WAI, and have a few issues<br>
&gt; to bring up. The first is relatively simple: what do we do about consuming<br>
&gt; the entire request body? Do we leave that as a task to the application, or<br>
&gt; should the server ensure that the entire request body is consumed?<br>
<br>
</div>Good question, is there something in the HTTP spec about this. I don&#39;t think<br>
so, and I think it would make sense to give up early if you consider the<br>
input as garbage.<br>
<div class="im"><br></div></blockquote><div>What do you mean by this? That we don&#39;t need to consume that input at all, or that the server should be held responsible for &quot;/dev/null&quot;ing  the data?<br><br></div>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div class="im">
&gt; Next, I have made the ResponseBodyClass typeclass specifically with the goal<br>
&gt; of allowing optimizations for lazy bytestrings and sending files. The former<br>
&gt; seems far-fetched; the latter provides the ability to use a sendfile system<br>
&gt; call instead of copying the file data into memory. However, in the presence<br>
&gt; of gzip encoding, how useful is this optimization?<br>
<br>
</div>It is useful anyway.<br>
<div class="im"><br>
&gt; Finally, there is a lot of discussion going on right now about enumerators.<br>
&gt; The question is whether the WAI protocol should use them. There are two<br>
&gt; places where they could replace the current offering: request body and<br>
&gt; response body.<br>
&gt;<br>
&gt; In my opinion, there is no major difference between the Hyena definition of<br>
&gt; an enumerator and the current response body sendByteString method. The<br>
&gt; former provides two extra features: there&#39;s an accumulating parameter passed<br>
&gt; around, and a method for indicating early termination. However, the<br>
&gt; accumulating parameter seems unnecesary to me in general, and when needed we<br>
&gt; can accomplish the same result with MVars. Early termination seems like<br>
&gt; something that would be unusual in the response context, and could be<br>
&gt; handled with exceptions.<br>
<br>
</div>IORefs could be sufficient (instead of MVars) but this seems a bit ugly<br>
compared to the accumulator. In the other hand sometimes you don&#39;t need<br>
the accumulator and so just pass a dump unit. If we live in IO yes exceptions<br>
could do that. However the point of the Either type is to remind you that<br>
you have two cases to handle.<br>
<div> </div></blockquote><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"><div class="im">
&gt; For the request body, there is a significant difference. However, I think<br>
&gt; that the current approach (called imperative elsewhere) is more in line with<br>
&gt; how most people would expect to program. At the same time, I believe there<br>
&gt; is no performance issue going either way, and am open to community input.<br>
<br>
</div>Why an imperative approach would be more in line when using a purely<br>
functional language?<br>
<div><div></div><div class="h5"><br>
Regards,<br>
<br>
--<br>
Nicolas Pouillard<br>
<a href="http://nicolaspouillard.fr" target="_blank">http://nicolaspouillard.fr</a><br>
</div></div></blockquote></div><br>Because I don&#39;t think it really *is* an imperative approach. For that matter, enumerators are frankly also an &quot;imperative approach.&quot; It&#39;s frankly a silly distinction IMO. The question is whether this is a *good* approach. I think passing in an output function fits very nicely with Haskell.<br>
<br>The question to me lies more on the request side than the response side. Basically, should the application provide a caller or a callee for reading the request body? Most of the time, the latter is simpler to write I believe.<br>
<br>Ha! I finally found the article I&#39;d read a while ago demonstrating this point in C. You can obviously disagree with the sentiment there, but I&#39;ve found the point to be true in Haskell as well: <a href="http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html">http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html</a><br>
<br>Michael<br></div>