共有HTTPマネージャを指定すると、requestBodySource
のrequestBody
で、長さが間違っていると、後続の要求が同じHTTPマネージャーに約20秒間。おそらくこの問題の原因となっている共有状態とGivesPopper
の相互作用についての何かがあるようです。ここでは、それを再現するサンプルコードです - 私たちは間違った長さのアップロードを送信するためにrequestb.inを使用し、次にrequestb.inで別の有効なURLを読み取ろうとします。ストリームに間違った長さを送信すると、HTTPマネージャの共有状態が破損する
{-# LANGUAGE OverloadedStrings #-}
import Data.Conduit.Binary (sourceFile)
import Network.HTTP.Conduit
import Network.HTTP.Types
import qualified Data.ByteString.Lazy as LBS
import System.IO
import Control.Monad.Trans.Resource (runResourceT)
import Control.Concurrent.Async (async,waitCatch)
import Control.Exception (displayException)
main :: IO()
main = do
{- Set up a ResourceT region with an available HTTP manager. -}
httpmgr <- newManager tlsManagerSettings
httpmgr2 <- newManager tlsManagerSettings
let file ="out" -- some byte contents with length > 1
lenb <- System.IO.withFile file ReadMode hFileSize
let inbytes = sourceFile file
initReq <- parseUrl "http://requestb.in/saxbx3sa"
putreq <- async $ runResourceT $ do
let req = initReq { method = "POST",
-- let us send wrong length in requestBodySource
requestBody = (requestBodySource (fromIntegral $ lenb - 1) inbytes)}
resp <- httpLbs req httpmgr
return (statusCode . responseStatus $ resp)
putreqRes <- waitCatch putreq
case putreqRes of
Left e -> print $ displayException $ e
Right r -> print $ r
getreq <- async $ runResourceT $ do
-- Let us do a GET on a different resource to see if it works
initReq <- parseUrl "http://requestb.in/1l15sz21"
let req = initReq { method = "GET"}
resp <- httpLbs req httpmgr
return (statusCode . responseStatus $ resp)
getreqRes <- waitCatch getreq
case getreqRes of
Left e -> print $ displayException $ e
Right r -> print $ r
出力 - 最初の悪いアップロードHTTP 200
としてを通じて移行し、その後のGET
要求がすぐにHTTP 400
エラーが発生します。GET
要求のための代わりに別のHTTP Managerを使用して
*Main> main
200
"StatusCodeException (Status {statusCode = 400, statusMessage = \"Bad Request\"})
[(\"Date\",\"Wed, 29 Jun 2016 11:54:59 GMT\"),(\"Content-Type\",\"text/html\"),
(\"Content-Length\",\"177\"),(\"Connection\",\"close\"),(\"Server\",\"-nginx\"),
(\"CF-RAY\",\"-\"),(\"X-Response-Body-Start\",\"<html>\\r\\n<head><title>400 Bad
Request</title></head>\\r\\n<body bgcolor=\\\"white\\\">\\r\\n<center><h1>400 Bad
Request</h1></center>\\r\\n<hr><center>cloudflare-
nginx</center>\\r\\n</body>\\r\\n</html>\\r\\n\"),(\"X-Request-URL\",\"GET
http://requestb.in:80/saxbx3sa\")] (CJ {expose = []})"
はHTTP 200
を返します。だから、httpマネージャの共有状態がここで問題になっているようです。
他の誰もそれを観察しましたか?私はHTTP Manager
のgithubの問題を調べましたが、これは報告されていません。ストリーミングの長さが間違っていると、ここで発生しているようにHTTPマネージャが破損してはいけません。
また、長さが正しいrequestBodySourceのソースファイルをシミュレートしましたが、シミュレートされたエラー(ネットワークの問題をシミュレートするため)が原因で途中で終了します。その場合、エラーはありません。だから、間違った長さで何の失敗もせずに送信すると、何らかの種類の共有状態がここで破損し、25秒以内に解放されるケースが1つしかないようです。
ここで何が起こっているかについて誰かが洞察を持っているなら、非常に役に立ちます。私は右ストリーミングの長さを強制する回避策があります。しかし、私は何が起きているのか理解したいので、生産現場でこのような状況に陥るのを避けることができます。
「http-conduit」の問題を開くのに役立つだろう – jberryman
投稿時に、バグだったのか、私のストリーミング機能の使い方が間違っているのか分かりませんでした部。 – Sal