
Hi again, I can't find a means to access raw POST data. Both Network.Wai.Request and Yesod.Request.Request appear to only contain pre-parsed values. What am I missing? J

On Tue, May 31, 2011 at 5:23 AM, Jeremy Hughes
Hi again,
I can't find a means to access raw POST data. Both Network.Wai.Request and Yesod.Request.Request appear to only contain pre-parsed values. What am I missing?
J
Hi Jeremy, There's an example in the haskell-web-rosetta repo[1] of getting the raw content of a request. (Next bit is slightly complicated.) The idea is that a Handler is in fact a monad transformer on top of an Iteratee. An Iteratee is a streaming data consumer, which allows us to parse the request body in constant space. The "consume" function used here turns that stream into a (strict) list of bytestrings, i.e., reads them all into memory. The use of lift is to deal with the fact that Handler is a monad transformer. So the simplest way to read the request body is the one shown in that example. But depending on what you want to do, you could also use a streaming approach via enumerators and thereby not read the entire request body into memory. For example, with JSON, you could use aeson[2] and attoparsec-enumerator[3]. But that requires a bit more work. What exactly do you want to do with the raw request body? Michael [1] https://github.com/snoyberg/haskell-web-rosetta/blob/master/json-request/yes... [2] http://hackage.haskell.org/package/aeson [3] http://hackage.haskell.org/package/attoparsec-enumerator

Hi Michael,
On Tue, May 31, 2011 at 3:11 PM, Michael Snoyman
Hi Jeremy,
There's an example in the haskell-web-rosetta repo[1] of getting the raw content of a request. (Next bit is slightly complicated.) The idea is that a Handler is in fact a monad transformer on top of an Iteratee. An Iteratee is a streaming data consumer, which allows us to parse the request body in constant space. The "consume" function used here turns that stream into a (strict) list of bytestrings, i.e., reads them all into memory. The use of lift is to deal with the fact that Handler is a monad transformer.
I'm reasonably ok with transformers. The requests in my app run inside a ReaderT ErrorT stack that uses phantom types to enforce some security invariants at compile time.
So the simplest way to read the request body is the one shown in that example. But depending on what you want to do, you could also use a streaming approach via enumerators and thereby not read the entire request body into memory. For example, with JSON, you could use aeson[2] and attoparsec-enumerator[3]. But that requires a bit more work.
What exactly do you want to do with the raw request body?
Somewhat similar to my previous question to this list: I need to write a POST/PUT proxy that passes the request body on without parsing it. Since some of the requests may attach image or video files, a constant memory solution is needed. Clearly I need to knuckle down and actually read the Enumerator documentation. It's a credit to the Yesod API that I haven't needed to until now :-). Cheers, Jeremy
Michael
[1] https://github.com/snoyberg/haskell-web-rosetta/blob/master/json-request/yes... [2] http://hackage.haskell.org/package/aeson [3] http://hackage.haskell.org/package/attoparsec-enumerator
participants (2)
-
Jeremy Hughes
-
Michael Snoyman