warp 3.0.2.3 → 3.0.3
raw patch · 8 files changed
+120/−28 lines, 8 filesdep ~basedep ~old-localedep ~time
Dependency ranges changed: base, old-locale, time
Files
- ChangeLog.md +44/−0
- Network/Wai/Handler/Warp.hs +18/−0
- Network/Wai/Handler/Warp/Header.hs +1/−1
- Network/Wai/Handler/Warp/Request.hs +8/−5
- Network/Wai/Handler/Warp/Run.hs +38/−7
- Network/Wai/Handler/Warp/Settings.hs +5/−0
- README.md +2/−0
- warp.cabal +4/−15
+ ChangeLog.md view
@@ -0,0 +1,44 @@+## 3.0.3++Modify flushing of request bodies. Previously, regardless of the size of the+request body, the entire body would be flushed. When uploading large files to a+web app that does not accept such files (e.g., returns a 413 too large status),+browsers would still send the entire request body and the servers will still+receive it.++The new behavior is to detect if there is a large amount of data still to be+consumed and, if so, immediately terminate the connection. In the case of+chunked request bodies, up to a maximum number of bytes is consumed before the+connection is terminated.++This is controlled by the new setting `setMaximumBodyFlush`. A value of+@Nothing@ will return the original behavior of flushing the entire body.++## 3.0.0++WAI no longer uses conduit for its streaming interface.++## 2.1.0++The `onOpen` and `onClose` settings now provide the `SockAddr` of the client,+and `onOpen` can return a `Bool` which will close the connection. The+`responseRaw` response has been added, which provides a more elegant way to+handle WebSockets than the previous `settingsIntercept`. The old settings+accessors have been deprecated in favor of new setters, which will allow+settings changes to be made in the future without breaking backwards+compatibility.++## 2.0.0++ResourceT is not used anymore. Request and Response is now abstract data types.+To use their constructors, Internal module should be imported.++## 1.3.9++Support for byte range requests.++## 1.3.7++Sockets now have `FD_CLOEXEC` set on them. This behavior is more secure, and+the change should not affect the vast majority of use cases. However, it+appeared that this is buggy and is fixed in 2.0.0.
Network/Wai/Handler/Warp.hs view
@@ -41,6 +41,7 @@ , setNoParsePath , setInstallShutdownHandler , setServerName+ , setMaximumBodyFlush -- ** Getters , getPort , getHost@@ -210,3 +211,20 @@ -- Since 3.0.2 setServerName :: ByteString -> Settings -> Settings setServerName x y = y { settingsServerName = x }++-- | The maximum number of bytes to flush from an unconsumed request body.+--+-- By default, Warp does not flush the request body so that, if a large body is+-- present, the connection is simply terminated instead of wasting time and+-- bandwidth on transmitting it. However, some clients do not deal with that+-- situation well. You can either change this setting to @Nothing@ to flush the+-- entire body in all cases, or in your application ensure that you always+-- consume the entire request body.+--+-- Default: 8192 bytes.+--+-- Since 3.0.3+setMaximumBodyFlush :: Maybe Int -> Settings -> Settings+setMaximumBodyFlush x y+ | Just x' <- x, x' < 0 = error "setMaximumBodyFlush: must be positive"+ | otherwise = y { settingsMaximumBodyFlush = x }
Network/Wai/Handler/Warp/Header.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings, FlexibleContexts #-} module Network.Wai.Handler.Warp.Header where
Network/Wai/Handler/Warp/Request.hs view
@@ -47,8 +47,10 @@ -> SockAddr -- ^ Peer's address. -> Source -- ^ Where HTTP request comes from. -> IO (Request+ ,Maybe (I.IORef Int) ,IndexedHeader) -- ^ -- 'Request' passed to 'Application',+ -- how many bytes remain to be consumed, if known -- 'IndexedHeader' of HTTP request for internal use, recvRequest settings conn ii addr src = do@@ -59,7 +61,7 @@ cl = idxhdr ! idxContentLength te = idxhdr ! idxTransferEncoding handleExpect conn httpversion expect- (rbody, bodyLength) <- bodyAndSource src cl te+ (rbody, remainingRef, bodyLength) <- bodyAndSource src cl te rbody' <- timeoutBody th rbody let req = Request { requestMethod = method@@ -77,7 +79,7 @@ , requestHeaderHost = idxhdr ! idxHost , requestHeaderRange = idxhdr ! idxRange }- return (req, idxhdr)+ return (req, remainingRef, idxhdr) where th = threadHandle ii @@ -111,15 +113,16 @@ -> Maybe HeaderValue -- ^ content length -> Maybe HeaderValue -- ^ transfer-encoding -> IO (IO ByteString+ ,Maybe (I.IORef Int) ,RequestBodyLength ) bodyAndSource src cl te | chunked = do csrc <- mkCSource src- return (readCSource csrc, ChunkedBody)+ return (readCSource csrc, Nothing, ChunkedBody) | otherwise = do- isrc <- mkISource src len- return (readISource isrc, bodyLen)+ isrc@(ISource _ remaining) <- mkISource src len+ return (readISource isrc, Just remaining, bodyLen) where len = toLength cl bodyLen = KnownLength $ fromIntegral len
Network/Wai/Handler/Warp/Run.hs view
@@ -293,7 +293,7 @@ errorResponse e = settingsOnExceptionResponse settings e recvSendLoop istatus fromClient = do- (req', idxhdr) <- recvRequest settings conn ii addr fromClient+ (req', mremainingRef, idxhdr) <- recvRequest settings conn ii addr fromClient let req = req' { isSecure = isSecure' } -- Let the application run for as long as it wants T.pause th@@ -326,18 +326,49 @@ Conc.yield when keepAlive $ do- -- flush the rest of the request body- flushBody $ requestBody req- T.resume th- recvSendLoop istatus fromClient+ -- If there is an unknown or large amount of data to still be read+ -- from the request body, simple drop this connection instead of+ -- reading it all in to satisfy a keep-alive request.+ case settingsMaximumBodyFlush settings of+ Nothing -> do+ flushEntireBody (requestBody req)+ T.resume th+ recvSendLoop istatus fromClient+ Just maxToRead -> do+ let tryKeepAlive = do+ -- flush the rest of the request body+ isComplete <- flushBody (requestBody req) maxToRead+ when isComplete $ do+ T.resume th+ recvSendLoop istatus fromClient+ case mremainingRef of+ Just ref -> do+ remaining <- readIORef ref+ when (remaining <= maxToRead) tryKeepAlive+ Nothing -> tryKeepAlive -flushBody :: IO ByteString -> IO ()-flushBody src =+flushEntireBody :: IO ByteString -> IO ()+flushEntireBody src = loop where loop = do bs <- src unless (S.null bs) loop++flushBody :: IO ByteString -- ^ get next chunk+ -> Int -- ^ maximum to flush+ -> IO Bool -- ^ True == flushed the entire body, False == we didn't+flushBody src =+ loop+ where+ loop toRead = do+ bs <- src+ let toRead' = toRead - S.length bs+ case () of+ ()+ | S.null bs -> return True+ | toRead' >= 0 -> loop toRead'+ | otherwise -> return False connSource :: Connection -> T.Handle -> IORef Bool -> IO ByteString connSource Connection { connRecv = recv } th istatus = do
Network/Wai/Handler/Warp/Settings.hs view
@@ -65,6 +65,10 @@ -- ^ Default server name if application does not set one. -- -- Since 3.0.2+ , settingsMaximumBodyFlush :: Maybe Int+ -- ^ See @setMaximumBodyFlush@.+ --+ -- Since 3.0.3 } -- | The default settings for the Warp server. See the individual settings for@@ -84,6 +88,7 @@ , settingsNoParsePath = False , settingsInstallShutdownHandler = const $ return () , settingsServerName = S8.pack $ "Warp/" ++ showVersion Paths_warp.version+ , settingsMaximumBodyFlush = Just 8192 } -- | Apply the logic provided by 'defaultExceptionHandler' to determine if an
+ README.md view
@@ -0,0 +1,2 @@+The premier WAI handler. For more information, see [Warp: A Haskell Web+Server](http://steve.vinoski.net/blog/2011/05/01/warp-a-haskell-web-server/).
warp.cabal view
@@ -1,5 +1,5 @@ Name: warp-Version: 3.0.2.3+Version: 3.0.3 Synopsis: A fast, light-weight web server for WAI applications. License: MIT License-file: LICENSE@@ -10,21 +10,10 @@ Build-Type: Simple Cabal-Version: >=1.8 Stability: Stable-Description:- The premier WAI handler. For more information, see <http://steve.vinoski.net/blog/2011/05/01/warp-a-haskell-web-server/>.- .- Changelog- .- [3.0.0] WAI no longer uses conduit for its streaming interface.- .- [2.1.0] The @onOpen@ and @onClose@ settings now provide the @SockAddr@ of the client, and @onOpen@ can return a @Bool@ which will close the connection. The @responseRaw@ response has been added, which provides a more elegant way to handle WebSockets than the previous @settingsIntercept@. The old settings accessors have been deprecated in favor of new setters, which will allow settings changes to be made in the future without breaking backwards compatibility.- .- [2.0.0] ResourceT is not used anymore. Request and Response is now abstract data types. To use their constructors, Internal module should be imported.- .- [1.3.9] Support for byte range requests.- .- [1.3.7] Sockets now have FD_CLOEXEC set on them. This behavior is more secure, and the change should not affect the vast majority of use cases. However, it appeared that this is buggy and is fixed in 2.0.0.+Description: The premier WAI handler. For more information, see <http://steve.vinoski.net/blog/2011/05/01/warp-a-haskell-web-server/>. extra-source-files: attic/hex+ ChangeLog.md+ README.md Flag network-bytestring Default: False