@@ -50,10 +50,12 @@ recvRequest :: Settings
5050 -> Source -- ^ Where HTTP request comes from.
5151 -> IO (Request
5252 ,Maybe (I.IORef Int)
53− ,IndexedHeader) -- ^
53+ ,IndexedHeader
54+ ,IO ByteString) -- ^
5455 -- 'Request' passed to 'Application',
5556 -- how many bytes remain to be consumed, if known
5657 -- 'IndexedHeader' of HTTP request for internal use,
58+ -- Body producing action used for flushing the request body
5759
5860recvRequest settings conn ii addr src = do
5961 hdrlines <- headerLines src
@@ -62,9 +64,12 @@ recvRequest settings conn ii addr src = do
6264 expect = idxhdr ! idxExpect
6365 cl = idxhdr ! idxContentLength
6466 te = idxhdr ! idxTransferEncoding
65− handleExpect conn httpversion expect
67+ handle100Continue = handleExpect conn httpversion expect
6668 (rbody, remainingRef, bodyLength) <- bodyAndSource src cl te
67− rbody' <- timeoutBody remainingRef th rbody
69+ -- body producing function which will produce '100-continue', if needed
70+ rbody' <- timeoutBody remainingRef th rbody handle100Continue
71+ -- body producing function which will never produce 100-continue
72+ rbodyFlush <- timeoutBody remainingRef th rbody (return ())
6873 let req = Request {
6974 requestMethod = method
7075 , httpVersion = httpversion
@@ -83,7 +88,7 @@ recvRequest settings conn ii addr src = do
8388 , requestHeaderHost = idxhdr ! idxHost
8489 , requestHeaderRange = idxhdr ! idxRange
8590 }
86− return (req, remainingRef, idxhdr)
91+ return (req, remainingRef, idxhdr, rbodyFlush)
8792 where
8893 th = threadHandle ii
8994
@@ -145,8 +150,9 @@ isChunked _ = False
145150timeoutBody :: Maybe (I.IORef Int) -- ^ remaining
146151 -> Timeout.Handle
147152 -> IO ByteString
153+ -> IO ()
148154 -> IO (IO ByteString)
149−timeoutBody remainingRef timeoutHandle rbody = do
155+timeoutBody remainingRef timeoutHandle rbody handle100Continue = do
150156 isFirstRef <- I.newIORef True
151157
152158 let checkEmpty =
@@ -162,6 +168,9 @@ timeoutBody remainingRef timeoutHandle rbody = do
162168 isFirst <- I.readIORef isFirstRef
163169
164170 when isFirst $ do
171+ -- Only check if we need to produce the 100 Continue status
172+ -- when asking for the first chunk of the body
173+ handle100Continue
165174 -- Timeout handling was paused after receiving the full request
166175 -- headers. Now we need to resume it to avoid a slowloris
167176 -- attack during request body sending.