on master help sign in
Merge branch 'reiddraper-warp/delayed-100-continue'
commit3231e02d6a8925f55aa04a78b1f8676ee7666d31 authorKazu Yamamoto <kazu@iij.ad.jp> dateThu 9 Apr 2015, 13:17 (12 years ago) parent3a2a7da4642f2c
2 files changed+19−10
warp/Network/Wai/Handler/Warp/Request.hs+14−5 warp/Network/Wai/Handler/Warp/Run.hs+5−5
warp/Network/Wai/Handler/Warp/Request.hs+14−5
@@ -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.
warp/Network/Wai/Handler/Warp/Run.hs+5−5
@@ -355,9 +355,9 @@ serveConnection conn ii origAddr transport settings app = do
355355 errorResponse e = settingsOnExceptionResponse settings e
356356
357357 http1 addr istatus src = do
358− (req', mremainingRef, idxhdr) <- recvRequest settings conn ii addr src
358+ (req', mremainingRef, idxhdr, nextBodyFlush) <- recvRequest settings conn ii addr src
359359 let req = req' { isSecure = isTransportSecure transport }
360− keepAlive <- processRequest istatus src req mremainingRef idxhdr
360+ keepAlive <- processRequest istatus src req mremainingRef idxhdr nextBodyFlush
361361 `E.catch` \e -> do
362362 -- Call the user-supplied exception handlers, passing the request.
363363 sendErrorResponse addr istatus e
@@ -366,7 +366,7 @@ serveConnection conn ii origAddr transport settings app = do
366366 return False
367367 when keepAlive $ http1 addr istatus src
368368
369− processRequest istatus src req mremainingRef idxhdr = do
369+ processRequest istatus src req mremainingRef idxhdr nextBodyFlush = do
370370 -- Let the application run for as long as it wants
371371 T.pause th
372372
@@ -405,13 +405,13 @@ serveConnection conn ii origAddr transport settings app = do
405405 -- reading it all in to satisfy a keep-alive request.
406406 case settingsMaximumBodyFlush settings of
407407 Nothing -> do
408− flushEntireBody (requestBody req)
408+ flushEntireBody nextBodyFlush
409409 T.resume th
410410 return True
411411 Just maxToRead -> do
412412 let tryKeepAlive = do
413413 -- flush the rest of the request body
414− isComplete <- flushBody (requestBody req) maxToRead
414+ isComplete <- flushBody nextBodyFlush maxToRead
415415 if isComplete then do
416416 T.resume th
417417 return True