此处提供完整的最小示例项目:https://github.com/chrissound/217
我已经通读了https://docs.servant.dev/en/v0.16/cookbook/using-free-client/UsingFreeClient.html
我最终的目标:
type API = "square"
:> Capture "n" Int
:> ReqBody '[JSON] ClientInfo
:> Get '[JSON] Int
api :: Proxy API
api = Proxy
myapitest = I.client api
getSquare :: Int -> ClientInfo -> Free ClientF Int
getSquare = Servant.Client.Free.client api
test :: IO ()
test = case getSquare 12 (ClientInfo "" "" 123 []) of
Pure n ->
putStrLn $ "ERROR: got pure result: " ++ show n
Free (Throw err) ->
putStrLn $ "ERROR: got error right away: " ++ show err
Free (RunRequest req k) -> do
burl <- parseBaseUrl "http://localhost:8000"
mgr <- HTTP.newManager HTTP.defaultManagerSettings
let req' = I.requestToClientRequest burl req
putStrLn $ "Making request: " ++ show req'
然而,这种方法似乎只是输出以下内容:
Making request: Request {
host = "localhost"
port = 8000
secure = False
requestHeaders = [("Accept","application/json;charset=utf-8,application/json"),("Content-Type","application/json;charset=utf-8")]
path = "/square/12"
queryString = ""
method = "GET"
proxy = Nothing
rawBody = False
redirectCount = 10
responseTimeout = ResponseTimeoutDefault
requestVersion = HTTP/1.1
}
当我期待一个身体有一些文本呈现。我期望这样做的原因是——因为如果向服务器发送请求并调试/检查它——我确实看到了一个带有文本的正文。所以我的问题是,为什么仆人说rawBody
是False
,我怎么才能真正让它展示身体?
实际发送HTTP请求的非调试代码是:
main :: IO ()
main = do
putStrLn "Hello, Haskell!"
run
test
queries = myapitest 10 (ClientInfo "" "" 123 [])
run :: IO ()
run = do
manager' <- newManager defaultManagerSettings
res <- runClientM queries (mkClientEnv manager' (BaseUrl Http "localhost" 8000 ""))
case res of
Right (message) -> do
pPrint message
Left err -> do
putStrLn $ "Error: "
pPrint err
答案是这很难,而且大多数解决方案都不适用于处理许多请求的应用程序。你需要把整个身体读成一个MVar,然后你就可以使用它了。您可以通过中间件执行此操作。然而,由于您消耗了整个主体,如果假设它被另一个中间件等使用,则需要将其放回流中。这仍然是服务存储库中的一个悬而未决的问题:https://github.com/haskell-servant/servant/issues/1120