记录http-conduit

时间:2018-05-07 12:48:10

标签: haskell bytestring 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,这表明存在某种无限循环。 / p>

此外,请求打印两次。

我之前的尝试类似,但没有修改r。之所以失败是因为在我完全阅读完回复之后,没有更多的回复数据需要阅读。

如果我将其替换为tlsManagerSettings,则http-conduit会再次发挥作用。

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

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

1 个答案:

答案 0 :(得分:1)

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

您遇到的问题是ByteString永远不会返回空的returnOnce :: Monoid a => a -> IO (IO a) returnOnce x = do ref <- newIORef x pure $ readIORef ref <* writeIORef ref mempty ,除非它始终如此。您需要提供更复杂的IO操作来捕获预期的行为。也许是这些方面的东西(未经测试):

select max(t1.ID) as ID
from YourTable as t1
left join YourTable as t2 on t1.ID = t2.ID+1
where (t1.name <> t2.name or t2.name is null)
  and t1.name = 'A';

至于如何调试这个?对通用方法不确定。我只是怀疑你可能需要一个解决方案,the docs for BodyReader证实了这一点。