Как доставить JSON через HTTP, используя Warp с Aeson

Я хочу создать высокопроизводительный API на основе HTTP, работающий на Haskell, используя warp в качестве HTTP-бэкенда.

Сервер должен возвращать данные JSON по запросу. Эти данные должны быть сериализованы с использованием Aeson

Тем не менее, деформация требует объекта ответа, в то время как Aeson возвращает ленивый ByteString s.

Как я могу связать обе библиотеки вместе? В этом вопросе меня интересует не разбор или маршрутизация запросов, а пример того, как связать обе библиотеки, чтобы получить правильный JSON с правильными заголовками.

Примечание: этот вопрос намеренно не требует каких-либо исследований, так как на него был дан ответ Q&A-style-ish. Смотрите мой ответ, если вам требуется исследовательская работа.

1 ответ

Решение

Я построю свой пример на примере минимальной деформации HaskellWiki.

Ради простоты я удалил любой код, такой как маршрутизация, заменив наиболее важные части заглушками и комментариями, где что размещать.

Данные JSON, которые мы будем сериализовывать в этом примере, представляют собой список ["a","b","c"], Тот же ответ (= JSON) будет возвращен для любого URL.

Проблема в соединении обеих библиотек заключается в том, что в то время как Warp требует Blaze Builder правильно построить свой ответ, в то время как Aeson возвращает (как вы сказали) ленивый ByteString, Соответствующая функция для соединения обоих называется fromLazyByteString,

{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import Data.Text (Text)
import Network.Wai
import Network.Wai.Handler.Warp
import Network.HTTP.Types (status200)
import Network.HTTP.Types.Header (hContentType)
import Blaze.ByteString.Builder.ByteString (fromLazyByteString)
import qualified Data.ByteString.UTF8 as BU

main = do
    let port = 3000
    putStrLn $ "Listening on port " ++ show port
    run port app

app :: Application
app req f = f $
    case pathInfo req of
        -- Place custom routes here
        _ -> anyRoute

-- The data that will be converted to JSON
jsonData = ["a","b","c"] :: [Text]

anyRoute = responseLBS
            status200
            [(hContentType, "application/json")]
            (encode jsonData)

Обновление 01.05.2015: пример исправления для Warp/WAI 3.x

Другие вопросы по тегам