Yesod - получение тела запроса для POST "Content-type: application/json"
Используя yesod 0.8.0, я пытаюсь получить тело сообщения сообщения из этого примера запроса:
curl -v -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"name":"oscar"}' http://localhost:3000/user/xyz
в моем обработчике единственный способ, которым я вижу это использовать
(pp, files) <- runRequestBody
Но это не удается из-за типа содержимого. Есть ли другая функция для этого?
Ответы
Ответ 1
Другие ответы кажутся довольно старыми и до того, как были добавлены функции, используемые ниже.
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)
Ответ 2
Здесь, как это сделать сейчас. Для будущих выпусков я надеюсь добавить некоторые удобные обертки; ввод по этому признаку.
Объяснение: Каждая функция обработчика живет в монаде GGHandler sub master (Iteratee ByteString IO)
. Это довольно сложно, но что это значит, так это то, что он превращает монад-конвертер вокруг Iteratee, который получает поток ByteStrings. Этот поток ByteStrings является необработанным телом запроса.
Итак, нам нужно использовать функцию перечислителя, чтобы взять весь поток ByteStrings и сохранить их в виде списка. И мы должны использовать функцию подъема, чтобы поднять ее на внутреннюю монаду (Iteratee). L.fromChunks затем преобразует из списка строгих ByteStrings в ленивую ByteString, которую вы можете анализировать с любой произвольной библиотекой JSON (Yesod стандартизирует на aeson).
Я предполагаю, что наиболее удобной функцией, которую я мог бы предоставить, было бы parseRequestJson :: GGHandler s m (Iteratee ByteString IO) (Maybe Data.Aeson.Value)
. Я могу добавить это в точечный выпуск yesod-json.
Ответ 3
В Yesod 1.0+ (и, возможно, раньше, не уверен) появляется следующее:
postRootR = do
wr <- waiRequest
bss <- lift $ lazyConsume $ requestBody wr
let requestBody = L.fromChunks bss