Журнал всех запросов и ответов для http-проводника

Я написал это ManagerSettings регистрировать все запросы и ответы для моего http-проводника приложения. (Кстати, я импортирую 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 }
                     }

Однако это не работает - когда я его использую, приложение зависает и пытается использовать всю оперативную память в машине после печати первого запроса и первого ответа, что предполагает какой-то бесконечный цикл.

Также запрос печатается дважды.

Я сделал предыдущую попытку, которая была похожа, но не изменила r, Это не удалось, потому что после того, как я полностью прочитал ответ, больше не было данных для чтения.

Если я заменю это на tlsManagerSettings, http-conduit снова работает

Мое приложение использует libstackexchange, которое я изменил, чтобы ManagerSettings быть настроенным Я использую http-проводник версии 2.2.4.

Как я могу диагностировать проблему? Как я могу это исправить?

1 ответ

Решение

managerModifyResponse не работает с Response ByteStringработает с Response BodyReader, где type BodyReader = IO ByteString вместе с договором, если он производит непустой ByteString есть больше информации, которую можно прочитать.

Проблема, с которой вы сталкиваетесь, заключается в том, что pure fullResponse никогда не возвращает пустое ByteString если это не всегда так. Вам нужно предоставить несколько более сложное действие ввода-вывода для захвата предполагаемого поведения. Может быть, что-то вроде этого (не проверено):

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

Что касается того, как отладить это? Не уверен насчет универсальных методов. Я просто подозревал, что вам, вероятно, нужно решение по этим направлениям, и документы дляBodyReader подтвердил это.

Другие вопросы по тегам