记录 http-conduit 的所有请求和响应

Log all requests and responses for http-conduit

我写这篇 ManagerSettings 是为了记录我的 http-conduit 应用程序的所有请求和响应。 (顺便说一下,我正在导入 ClassyPrelude)。

tracingManagerSettings :: ManagerSettings
tracingManagerSettings =
  tlsManagerSettings { managerModifyRequest = \req -> do
                         putStr "TRACE: "
                         print req
                         putStrLn ""
                         pure req
                     , managerModifyResponse = \r -> do
                         responseChunks <- brConsume $ responseBody r
                         let fullResponse = mconcat responseChunks
                         putStr "TRACE: RESPONSE: "
                         putStrLn $ decodeUtf8 fullResponse
                         pure $ r { responseBody = pure fullResponse }
                     }

但是,它不起作用 - 当我使用它时,应用程序挂起并试图在打印第一个请求和第一个响应后消耗机器中的所有 RAM,这表明存在某种无限循环。

此外,请求被打印了两次。

我之前做过类似的尝试,但没有修改r。那失败了,因为在我已经完全读取响应之后,没有更多的响应数据可以读取。

如果我将其替换为 tlsManagerSettingshttp-conduit 将再次起作用。

我的应用程序正在使用 libstackexchange,我对其进行了修改以允许自定义 ManagerSettings。我正在使用 http-conduit 版本 2.2.4.

如何诊断问题?我该如何解决?

managerModifyResponse 不适用于 Response ByteString,它适用于 Response BodyReader,其中 type BodyReader = IO ByteString 以及如果它产生非空的合同ByteString还有更多的输入可以读取。

您 运行 遇到的问题是 pure fullResponse 永远不会 returns 空 ByteString 除非它总是如此。您需要提供稍微复杂一些的 IO 操作来捕获预期的行为。也许沿着这些路线(未经测试):

returnOnce :: Monoid a => a -> IO (IO a)
returnOnce x = do
    ref <- newIORef x
    pure $ readIORef ref <* writeIORef ref mempty

至于如何调试呢?不确定通用方法。我只是怀疑您可能需要这样的解决方案,并且 the docs for BodyReader 确认了它。