1

我写这个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. 那失败了,因为在我已经完全阅读了响应之后,没有更多的响应数据可以读取。

如果我将其替换为tlsManagerSettings,则http-conduit再次工作。

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

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

4

1 回答 1

1

managerModifyResponse不适用于 a Response ByteString,它适用于 a Response BodyReadertype BodyReader = IO ByteString与合同一起,如果它产生非空ByteString,则可以读取更多输入。

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

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

至于如何调试这个?不确定通用方法。我只是怀疑您可能需要这些方面的解决方案,并且文档BodyReader确认了它。

于 2018-05-07T13:07:43.573 回答