Обработка параметров запроса HTTP GET в Warp

Используя сервер warp HTTP, я хочу обрабатывать параметры HTTP-запроса.

Легко (см., например, здесь) заставить Warp отображать что-то для таких URL-адресов, как

http://localhost:3000/foo

Как я могу сделать это визуализировать

http://localhost:3000/foo?id=bar

таким образом, что содержимое зависит от параметра запроса id?

Кроме того, как я могу справиться, если такого параметра нет?

Как доставить JSON через HTTP с помощью Warp с Aeson


person Uli Köhler    schedule 04.03.2014    source источник


Ответы (1)


Я построю свой пример на основе предыдущего ответа.

Самый важный модуль в данном контексте это Network.HTTP.Types, в частности Query.

Вы можете получить Query из WAI Request, используя QueryString.

Поскольку Query — это не что иное, как [(ByteString, Maybe ByteString)], мы можем использовать lookup из базовой библиотеки, чтобы найти соответствующий атрибут.

Однако, поскольку lookup оборачивает тип в Maybe, мы получаем Maybe (Maybe ByteString). Мой пример содержит довольно уродливо звучащую функцию maybeMaybeToMaybe для преобразования этого в Maybe ByteString.

В примере возвращается простой текстовый ответ (по любому URL-адресу), который содержит параметр запроса id. Поскольку он просто использует show для примера URL

http://localhost:3000/foo?id=bar

это дает

Query parameter: Just "foobar"

тогда как для

http://localhost:3000/

это дает

Query parameter: Nothing

Вот полный исходный код:

{-# LANGUAGE OverloadedStrings #-}
import Control.Applicative ((<$>))
import Control.Monad
import Network.Wai
import Network.Wai.Handler.Warp
import Network.HTTP.Types (status200)
import Network.HTTP.Types.Header (hContentType)
import Blaze.ByteString.Builder.Char.Utf8 (fromString)
import Data.ByteString (ByteString)

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

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

anyRoute req =
    let query = queryString req :: [(ByteString, Maybe ByteString)]
        idParam = join $ lookup "id" query :: Maybe ByteString
    in responseBuilder
            status200
            [(hContentType, "text/plain")]
            $ fromString $ "Query parameter: " ++ (show idParam)
person Uli Köhler    schedule 04.03.2014
comment
maybeMaybeToMaybe это всего лишь Control.Monad.join. - person Michael Snoyman; 05.03.2014
comment
@MichaelSnoyman Большое спасибо, что заметили это! Я заменил maybeMaybeToMaybe на join в приведенном выше коде, что сделало его намного проще! Кроме того, я удалил внутренний импорт с помощью responseBuilder - person Uli Köhler; 05.03.2014