<div dir="ltr"><br><br><div class="gmail_quote">On Sat, May 22, 2010 at 11:15 PM, Gregory Collins <span dir="ltr">&lt;<a href="mailto:greg@gregorycollins.net">greg@gregorycollins.net</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">Michael Snoyman &lt;<a href="mailto:michael@snoyman.com">michael@snoyman.com</a>&gt; writes:<br>
<br>
&gt; Congratulations on the release. I was interested in seeing how this<br>
&gt; would work as a WAI handler, and came across some questions:<br>
&gt;<br>
&gt; * I noticed that the Method datatype is restricted to a set of<br>
&gt; specific methods. Seeing as the list of methods can be expanded[1],<br>
&gt; why was this chosen?<br>
<br>
</div>The answer is &quot;no particular reason&quot; -- nobody really uses this. I think<br>
you&#39;re right that this makes us technically out of spec, if it becomes<br>
an issue for anyone we&#39;ll add a custom constructor later.<br>
<div class="im"><br></div></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class="im">
<br>
&gt; * The CIByteString datatype provides no way of accessing directly the<br>
&gt; lower-case version of the bytestring, or of setting it. Seeing as WAI<br>
&gt; already lower-cases the headers (following your suggestion btw) it<br>
&gt; would be more efficient to only do this once. Would you consider<br>
&gt; exposing the constructor?<br>
<br>
</div>Would you accept:<br>
<br>
    ciToLower :: CIByteString -&gt; ByteString<br>
<br>
instead? I prefer opaque datatypes in general. We didn&#39;t see a need for<br>
that use-case, the idea was that the string representation would be the<br>
same but we would do a case-insensitive compare.<br>
<div class="im"><br></div></blockquote><div>Well, that solves half the problem: I also would like to be able to hand in a lower-case version when converting from the WAI ResponseHeader to a CIByteString.</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">
<br>
&gt; * For simplicity at the moment, I decided to use the getRequestBody<br>
&gt; function, but it seems to be returning an empty result. Is there a<br>
&gt; known gotcha here?<br>
<br>
</div>If the POST body has content-type &quot;application/x-www-form-urlencoded&quot; we<br>
parse it for you and put the fields in the parameter mapping. If this<br>
isn&#39;t your case I&#39;d appreciate a bug report. This is a place where we<br>
made a different design decision than you did -- a WAI application which<br>
expects to parse the POST body itself won&#39;t work. I&#39;ll think about<br>
adding a knob to make this behaviour optional.<br>
<div class="im"><br></div></blockquote><div>I&#39;d appreciate such a knob. Out of curiosity, do you also parse multi-part data? </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">
<br>
&gt; Overall, writing the WAI wrapper is pretty straight-forward. The main<br>
&gt; problem is that the WAI request body does not require an inversion of<br>
&gt; control approach, while the Snap version does; some usage of lazy I/O<br>
&gt; here could solve the problem, though that&#39;s obviously sub-optimal.<br>
<br>
</div>A Chan &amp; a forkIO could work here also (we&#39;ve discussed that one before<br>
I think.)<br>
<div class="im"><br></div></blockquote><div>You&#39;re right; it doesn&#39;t actually require the lazy I/O bit, just the forkIO. Not that I&#39;m crazy about that solution either. </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im"><br>
&gt; Also, it seems a little unclear whether the writeBS et al functions<br>
&gt; store the body in memory before returning the result, though the<br>
&gt; documentation implies it. Could you provide some clarifications?<br>
<br>
</div>The Snap monad carries a &quot;Response&quot; in its state, with &quot;rspBody&quot; being<br>
an output Enumerator. The &quot;writeBS&quot; function composes &quot;enumBS foo&quot; with<br>
the Enumerator from that state; so when you call writeBS you&#39;re really<br>
building up a *program* to send the response body out later. So yes, we<br>
hang onto that data until the request is served.<br>
<br></blockquote><div>That&#39;s what it looked like to me; maybe you could update the docs to make that clear. I&#39;d hate for people to accidentally kill their performance.</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

If you want to stream in O(1) space you need to provide an Enumerator to<br>
do so; the Enumerator has access to the IO monad though. We provide<br>
writeBS/writeLBS for those situations in which it&#39;s<br>
convenient/appropriate to build up the entire response in memory.<br>
<div><div></div><div class="h5"><br></div></div></blockquote><div>I figured I&#39;d end up writing that, but I just wanted to test things out the simple way first via writeLBS. I&#39;ll have to wait in any event for the ability to bypass automatic request body parsing.</div>
<div><br></div><div>Michael</div></div></div>