Using yesod 0.8.0, I'm trying to retrieve the body of a post message from this example request:
curl -v -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"name":"oscar"}' http://localhost:3000/user/xyz
in my handler the only way I see it is to use
(pp, files) <- runRequestBody
But this fails because of the content type. Is there another function to do this?
The other answers seem to be pretty old and from before the functions used below were added.
postFooR :: Handler Value
postFooR = do
foo <- requireJsonBody :: Handler Foo -- get the json body as Foo (assumes FromJSON instance)
returnJson foo -- return json (assumes ToJSON instance)
Here's how to do it now. For future releases, I'm hoping to add some convenience wrappers; input on this is appreciated.
The explanation: Each handler function lives in a GGHandler sub master (Iteratee ByteString IO)
monad. That's fairly complicated, but what it means is that it's a Handler monad transformer around an Iteratee that receives a stream of ByteStrings. That stream of ByteStrings is the raw request body.
So we need to use enumerator's consume function to take that entire stream of ByteStrings and store them as a list. And we need to use the lift function to lift this to the inner monad (the Iteratee). L.fromChunks then converts from a list of strict ByteStrings to a lazy ByteString, which you can parse with any arbitrary JSON library (Yesod is standardizing on aeson).
My guess is that the most convenient function I could provide would be parseRequestJson :: GGHandler s m (Iteratee ByteString IO) (Maybe Data.Aeson.Value)
. I can add that in a point release of yesod-json.
In Yesod 1.0+ (and maybe earlier, not sure), the following appears to work:
postRootR = do
wr <- waiRequest
bss <- lift $ lazyConsume $ requestBody wr
let requestBody = L.fromChunks bss
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With