packages feed

warp 3.0.9.3 → 3.0.10

raw patch · 4 files changed

+71/−9 lines, 4 filesdep +vault

Dependencies added: vault

Files

ChangeLog.md view
@@ -1,3 +1,13 @@+## 3.0.10++* Fix [missing `IORef` tweak](https://github.com/yesodweb/wai/issues/351)+* Disable timeouts as soon as request body is fully consumed. This addresses+  the common case of a non-chunked request body. Previously, we would wait+  until a zero-length `ByteString` is returned, but that is suboptimal for some+  cases. For more information, see [issue+  351](https://github.com/yesodweb/wai/issues/351).+* Add `pauseTimeout` function+ ## 3.0.9.3  * Don't serve a 416 status code for 0-length files [keter issue #75](https://github.com/snoyberg/keter/issues/75)
Network/Wai/Handler/Warp.hs view
@@ -17,6 +17,21 @@ ---------------------------------------------------------  -- | A fast, light-weight HTTP server handler for WAI.+--+-- Note on slowloris timeouts: to prevent slowloris attacks, timeouts are used+-- at various points in request receiving and response sending. One interesting+-- corner case is partial request body consumption; in that case, Warp's+-- timeout handling is still in effect, and the timeout will not be triggered+-- again. Therefore, it is recommended that once you start consuming the+-- request body, you either:+--+-- * consume the entire body promptly+--+-- * call the 'pauseTimeout' function+--+-- For more information, see <https://github.com/yesodweb/wai/issues/351>.+--+-- module Network.Wai.Handler.Warp (     -- * Run a Warp server     run@@ -73,6 +88,8 @@   , Port   , InvalidRequest (..)   , ConnSendFileOverride (..)+    -- * Per-request utilities+  , pauseTimeout     -- * Connection   , Connection (..)   , socketConnection@@ -105,10 +122,12 @@ import Network.Wai.Handler.Warp.Timeout import Network.Wai.Handler.Warp.Types import Control.Exception (SomeException)-import Network.Wai (Request, Response)+import Network.Wai (Request, Response, vault) import Network.Socket (SockAddr) import Data.Streaming.Network (HostPreference) import Data.ByteString (ByteString)+import qualified Data.Vault.Lazy as Vault+import Data.Maybe (fromMaybe)  -- | Port to listen on. Default value: 3000 --@@ -284,3 +303,12 @@ -- Since 3.0.5 setProxyProtocolOptional :: Settings -> Settings setProxyProtocolOptional y = y { settingsProxyProtocol = ProxyProtocolOptional }++-- | Explicitly pause the slowloris timeout.+--+-- This is useful for cases where you partially consume a request body. For+-- more information, see <https://github.com/yesodweb/wai/issues/351>+--+-- Since 3.0.10+pauseTimeout :: Request -> IO ()+pauseTimeout = fromMaybe (return ()) . Vault.lookup pauseTimeoutKey . vault
Network/Wai/Handler/Warp/Request.hs view
@@ -6,6 +6,7 @@ module Network.Wai.Handler.Warp.Request (     recvRequest   , headerLines+  , pauseTimeoutKey   ) where  import qualified Control.Concurrent as Conc (yield)@@ -16,7 +17,6 @@ import qualified Data.ByteString.Unsafe as SU import qualified Data.CaseInsensitive as CI import qualified Data.IORef as I-import Data.Monoid (mempty) import qualified Network.HTTP.Types as H import Network.Socket (SockAddr) import Network.Wai@@ -30,6 +30,8 @@ import Network.Wai.Internal import Prelude hiding (lines) import Control.Monad (when)+import qualified Data.Vault.Lazy as Vault+import System.IO.Unsafe (unsafePerformIO)  ---------------------------------------------------------------- @@ -62,7 +64,7 @@         te = idxhdr ! idxTransferEncoding     handleExpect conn httpversion expect     (rbody, remainingRef, bodyLength) <- bodyAndSource src cl te-    rbody' <- timeoutBody th rbody+    rbody' <- timeoutBody remainingRef th rbody     let req = Request {             requestMethod     = method           , httpVersion       = httpversion@@ -74,7 +76,9 @@           , isSecure          = False           , remoteHost        = addr           , requestBody       = rbody'-          , vault             = mempty+          , vault             = Vault.insert pauseTimeoutKey+                                (Timeout.pause th)+                                Vault.empty           , requestBodyLength = bodyLength           , requestHeaderHost = idxhdr ! idxHost           , requestHeaderRange = idxhdr ! idxRange@@ -138,18 +142,31 @@  ---------------------------------------------------------------- -timeoutBody :: Timeout.Handle -> IO ByteString -> IO (IO ByteString)-timeoutBody timeoutHandle rbody = do+timeoutBody :: Maybe (I.IORef Int) -- ^ remaining+            -> Timeout.Handle+            -> IO ByteString+            -> IO (IO ByteString)+timeoutBody remainingRef timeoutHandle rbody = do     isFirstRef <- I.newIORef True +    let checkEmpty =+            case remainingRef of+                Nothing -> return . S.null+                Just ref -> \bs -> if S.null bs+                    then return True+                    else do+                        x <- I.readIORef ref+                        return $! x <= 0+     return $ do         isFirst <- I.readIORef isFirstRef -        when isFirst $+        when isFirst $ do             -- Timeout handling was paused after receiving the full request             -- headers. Now we need to resume it to avoid a slowloris             -- attack during request body sending.             Timeout.resume timeoutHandle+            I.writeIORef isFirstRef False          bs <- rbody @@ -157,7 +174,8 @@         -- because the application is not interested in more bytes, or         -- because there is no more data available, pause the timeout         -- handler again.-        when (S.null bs) (Timeout.pause timeoutHandle)+        isEmpty <- checkEmpty bs+        when isEmpty (Timeout.pause timeoutHandle)          return bs @@ -247,3 +265,7 @@ checkCR bs pos = if pos > 0 && 13 == S.index bs p then p else pos -- 13 is CR   where     !p = pos - 1++pauseTimeoutKey :: Vault.Key (IO ())+pauseTimeoutKey = unsafePerformIO Vault.newKey+{-# NOINLINE pauseTimeoutKey #-}
warp.cabal view
@@ -1,5 +1,5 @@ Name:                warp-Version:             3.0.9.3+Version:             3.0.10 Synopsis:            A fast, light-weight web server for WAI applications. License:             MIT License-file:        LICENSE@@ -46,6 +46,7 @@                    , wai                       >= 3.0      && < 3.1                    , text                    , streaming-commons         >= 0.1.10+                   , vault                     >= 0.3   if flag(network-bytestring)       Build-Depends: network                   >= 2.2.1.5  && < 2.2.3                    , network-bytestring        >= 0.1.3    && < 0.1.4@@ -143,6 +144,7 @@                    , text                    , streaming-commons         >= 0.1.10                    , async+                   , vault   if flag(use-bytestring-builder)       Build-Depends: bytestring                < 0.10.2.0                    , bytestring-builder