<div dir="ltr"><br><br><div class="gmail_quote">On Sat, May 22, 2010 at 11:15 PM, Gregory Collins <span dir="ltr"><<a href="mailto:greg@gregorycollins.net">greg@gregorycollins.net</a>></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 <<a href="mailto:michael@snoyman.com">michael@snoyman.com</a>> writes:<br>
<br>
> Congratulations on the release. I was interested in seeing how this<br>
> would work as a WAI handler, and came across some questions:<br>
><br>
> * I noticed that the Method datatype is restricted to a set of<br>
> specific methods. Seeing as the list of methods can be expanded[1],<br>
> why was this chosen?<br>
<br>
</div>The answer is "no particular reason" -- nobody really uses this. I think<br>
you're right that this makes us technically out of spec, if it becomes<br>
an issue for anyone we'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>
> * The CIByteString datatype provides no way of accessing directly the<br>
> lower-case version of the bytestring, or of setting it. Seeing as WAI<br>
> already lower-cases the headers (following your suggestion btw) it<br>
> would be more efficient to only do this once. Would you consider<br>
> exposing the constructor?<br>
<br>
</div>Would you accept:<br>
<br>
ciToLower :: CIByteString -> ByteString<br>
<br>
instead? I prefer opaque datatypes in general. We didn'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>
> * For simplicity at the moment, I decided to use the getRequestBody<br>
> function, but it seems to be returning an empty result. Is there a<br>
> known gotcha here?<br>
<br>
</div>If the POST body has content-type "application/x-www-form-urlencoded" we<br>
parse it for you and put the fields in the parameter mapping. If this<br>
isn't your case I'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't work. I'll think about<br>
adding a knob to make this behaviour optional.<br>
<div class="im"><br></div></blockquote><div>I'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>
> Overall, writing the WAI wrapper is pretty straight-forward. The main<br>
> problem is that the WAI request body does not require an inversion of<br>
> control approach, while the Snap version does; some usage of lazy I/O<br>
> here could solve the problem, though that's obviously sub-optimal.<br>
<br>
</div>A Chan & a forkIO could work here also (we've discussed that one before<br>
I think.)<br>
<div class="im"><br></div></blockquote><div>You're right; it doesn't actually require the lazy I/O bit, just the forkIO. Not that I'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>
> Also, it seems a little unclear whether the writeBS et al functions<br>
> store the body in memory before returning the result, though the<br>
> documentation implies it. Could you provide some clarifications?<br>
<br>
</div>The Snap monad carries a "Response" in its state, with "rspBody" being<br>
an output Enumerator. The "writeBS" function composes "enumBS foo" with<br>
the Enumerator from that state; so when you call writeBS you'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's what it looked like to me; maybe you could update the docs to make that clear. I'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'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'd end up writing that, but I just wanted to test things out the simple way first via writeLBS. I'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>