packages feed

warp 3.2.11.1 → 3.2.11.2

raw patch · 5 files changed

+45/−19 lines, 5 files

Files

ChangeLog.md view
@@ -1,3 +1,8 @@+## 3.2.11.2++* Don't throw exceptions when closing a keep-alive connection+  [#618](https://github.com/yesodweb/wai/issues/618)+ ## 3.2.11.1  * Move exception handling to top of thread (fixes
Network/Wai/Handler/Warp/Request.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-} {-# OPTIONS_GHC -fno-warn-deprecations #-}  module Network.Wai.Handler.Warp.Request (@@ -8,12 +9,14 @@   , headerLines   , pauseTimeoutKey   , getFileInfoKey+  , NoKeepAliveRequest (..)   ) where  import qualified Control.Concurrent as Conc (yield)-import Control.Exception (throwIO)+import Control.Exception (throwIO, Exception) import Data.Array ((!)) import Data.ByteString (ByteString)+import Data.Typeable (Typeable) import qualified Data.ByteString as S import qualified Data.ByteString.Unsafe as SU import qualified Data.CaseInsensitive as CI@@ -46,7 +49,8 @@  -- | Receiving a HTTP request from 'Connection' and parsing its header --   to create 'Request'.-recvRequest :: Settings+recvRequest :: Bool -- ^ first request on this connection?+            -> Settings             -> Connection             -> InternalInfo1             -> SockAddr -- ^ Peer's address.@@ -61,8 +65,8 @@             -- 'IndexedHeader' of HTTP request for internal use,             -- Body producing action used for flushing the request body -recvRequest settings conn ii1 addr src = do-    hdrlines <- headerLines src+recvRequest firstRequest settings conn ii1 addr src = do+    hdrlines <- headerLines firstRequest src     (method, unparsedPath, path, query, httpversion, hdr) <- parseHeaderLines hdrlines     let idxhdr = indexRequestHeader hdr         expect = idxhdr ! fromEnum ReqExpect@@ -103,12 +107,20 @@  ---------------------------------------------------------------- -headerLines :: Source -> IO [ByteString]-headerLines src = do+headerLines :: Bool -> Source -> IO [ByteString]+headerLines firstRequest src = do     bs <- readSource src     if S.null bs-        then throwIO ConnectionClosedByPeer+        -- When we're working on a keep-alive connection and trying to+        -- get the second or later request, we don't want to treat the+        -- lack of data as a real exception. See the http1 function in+        -- the Run module for more details.+        then if firstRequest then throwIO ConnectionClosedByPeer else throwIO NoKeepAliveRequest         else push src (THStatus 0 id id) bs++data NoKeepAliveRequest = NoKeepAliveRequest+    deriving (Show, Typeable)+instance Exception NoKeepAliveRequest  ---------------------------------------------------------------- 
Network/Wai/Handler/Warp/Run.hs view
@@ -341,7 +341,7 @@         writeIORef istatus True         leftoverSource src bs         addr <- getProxyProtocolAddr src-        http1 addr istatus src `E.catch` \e -> do+        http1 True addr istatus src `E.catch` \e -> do             sendErrorResponse addr istatus e             throwIO (e :: SomeException)   where@@ -402,8 +402,8 @@      errorResponse e = settingsOnExceptionResponse settings e -    http1 addr istatus src = do-        (req', mremainingRef, idxhdr, nextBodyFlush, ii) <- recvRequest settings conn ii1 addr src+    http1 firstRequest addr istatus src = do+        (req', mremainingRef, idxhdr, nextBodyFlush, ii) <- recvRequest firstRequest settings conn ii1 addr src         let req = req' { isSecure = isTransportSecure transport }         keepAlive <- processRequest istatus src req mremainingRef idxhdr nextBodyFlush ii             `E.catch` \e -> do@@ -412,7 +412,16 @@                 settingsOnException settings (Just req) e                 -- Don't throw the error again to prevent calling settingsOnException twice.                 return False-        when keepAlive $ http1 addr istatus src++        -- When doing a keep-alive connection, the other side may just+        -- close the connection. We don't want to treat that as an+        -- exceptional situation, so we pass in False to http1 (which+        -- in turn passes in False to recvRequest), indicating that+        -- this is not the first request. If, when trying to read the+        -- request headers, no data is available, recvRequest will+        -- throw a NoKeepAliveRequest exception, which we catch here+        -- and ignore. See: https://github.com/yesodweb/wai/issues/618+        when keepAlive $ http1 False addr istatus src `E.catch` \NoKeepAliveRequest -> return ()      processRequest istatus src req mremainingRef idxhdr nextBodyFlush ii = do         -- Let the application run for as long as it wants
test/RequestSpec.hs view
@@ -63,29 +63,29 @@   describe "headerLines" $ do       it "can handle a nomarl case" $ do           src <- mkSourceFunc ["Status: 200\r\nContent-Type: text/plain\r\n\r\n"] >>= mkSource-          x <- headerLines src+          x <- headerLines True src           x `shouldBe` ["Status: 200", "Content-Type: text/plain"]        it "can handle a nasty case (1)" $ do           src <- mkSourceFunc ["Status: 200", "\r\nContent-Type: text/plain", "\r\n\r\n"] >>= mkSource-          x <- headerLines src+          x <- headerLines True src           x `shouldBe` ["Status: 200", "Content-Type: text/plain"]        it "can handle a nasty case (1)" $ do           src <- mkSourceFunc ["Status: 200", "\r", "\nContent-Type: text/plain", "\r", "\n\r\n"] >>= mkSource-          x <- headerLines src+          x <- headerLines True src           x `shouldBe` ["Status: 200", "Content-Type: text/plain"]        it "can handle a nasty case (1)" $ do           src <- mkSourceFunc ["Status: 200", "\r", "\n", "Content-Type: text/plain", "\r", "\n", "\r", "\n"] >>= mkSource-          x <- headerLines src+          x <- headerLines True src           x `shouldBe` ["Status: 200", "Content-Type: text/plain"]        it "can handle an illegal case (1)" $ do           src <- mkSourceFunc ["\nStatus:", "\n 200", "\nContent-Type: text/plain", "\r\n\r\n"] >>= mkSource-          x <- headerLines src+          x <- headerLines True src           x `shouldBe` []-          y <- headerLines src+          y <- headerLines True src           y `shouldBe` ["Status: 200", "Content-Type: text/plain"]    where@@ -111,7 +111,7 @@                     writeIORef ref z                     return y     src' <- mkSource src-    res <- headerLines src'+    res <- headerLines True src'     return (res, src')  consumeLen :: Int -> Source -> IO S8.ByteString
warp.cabal view
@@ -1,5 +1,5 @@ Name:                warp-Version:             3.2.11.1+Version:             3.2.11.2 Synopsis:            A fast, light-weight web server for WAI applications. License:             MIT License-file:        LICENSE