当然!这里要注意的奇怪的 Haskell 事情是 Haskell 的记录系统。当您使用 URL 字符串调用 parseUrl 时,http-conduit 会返回一个 Request 记录并填写一些默认值,但库希望您填写其余部分。
例如,parseUrl 始终返回一个Request,并将 HTTP 方法设置为 GET。我们可以使用记录更新语法来覆盖该值——在花括号中附加新的键和值。
{-# LANGUAGE OverloadedStrings #-}
module Lib where
import Data.Aeson
import Network.HTTP.Client
buildRequest :: String -> RequestBody -> IO Request
buildRequest url body = do
nakedRequest <- parseRequest url
return (nakedRequest { method = "POST", requestBody = body })
send :: RequestBody -> IO ()
send s = do
manager <- newManager defaultManagerSettings
request <- buildRequest "http://httpbin.org/post" s
response <- httpLbs request manager
let Just obj = decode (responseBody response)
print (obj :: Object)
如果你在 GHCi 中运行它,你应该能够发送 POST 到 httpbin:
λ> :set -XOverloadedStrings
λ> send "hello there"
fromList [("origin",String "<snip>")
,("args",Object (fromList []))
,("json",Null)
,("data",String "hello there")
,("url",String "http://httpbin.org/post")
,("headers",Object (fromList [("Accept-Encoding",String "gzip")
,("Host",String "httpbin.org")
,("Content-Length",String "11")]))
,("files",Object (fromList []))
,("form",Object (fromList []))]
您还需要 OverloadedStrings 扩展。没有它,会发生两件事:
nakedRequest { method = "POST" } 不会进行类型检查,因为库需要来自 bytestring 库的(严格)ByteString。默认情况下,"POST" 和所有字符串文字的类型为 String 又名 [Char]。虽然有一个名为pack 的函数接受String 并返回ByteString,但打开重载字符串要简单得多。编译器会自动代表您调用pack。不止于此;有关详细信息,请参阅Oliver's blog post。
另一个不会进行类型检查的表达式是send "hello there"。 send 需要 RequestBody。虽然在某处还有一个函数类型为 String -> RequestBody,但打开重载字符串并让编译器为您调用它要容易得多。