packages feed

warp 3.4.20 → 3.4.21

raw patch · 9 files changed

+109/−18 lines, 9 filesdep ~networkPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: network

API changes (from Hackage documentation)

+ Network.Wai.Handler.Warp: getUnsafeClose :: Settings -> Bool
+ Network.Wai.Handler.Warp: setUnsafeClose :: Bool -> Settings -> Settings
+ Network.Wai.Handler.Warp.Internal: [settingsUnsafeClose] :: Settings -> Bool
- Network.Wai.Handler.Warp.Internal: Settings :: Port -> HostPreference -> (Maybe Request -> SomeException -> IO ()) -> Maybe (SockAddr -> SomeException -> IO ()) -> (SomeException -> Response) -> (SockAddr -> IO Bool) -> (SockAddr -> IO ()) -> Int -> Maybe Manager -> Int -> Int -> IO () -> (((forall a. () => IO a -> IO a) -> IO ()) -> IO ()) -> (Socket -> IO (Socket, SockAddr)) -> Bool -> (IO () -> IO ()) -> ByteString -> Maybe Int -> ProxyProtocol -> Int -> Bool -> (Request -> Status -> Maybe Integer -> IO ()) -> (Request -> ByteString -> Integer -> IO ()) -> Maybe Int -> Int -> Int -> Int -> Maybe ByteString -> Int -> Maybe Counter -> Maybe ServerState -> Settings
+ Network.Wai.Handler.Warp.Internal: Settings :: Port -> HostPreference -> (Maybe Request -> SomeException -> IO ()) -> Maybe (SockAddr -> SomeException -> IO ()) -> (SomeException -> Response) -> (SockAddr -> IO Bool) -> (SockAddr -> IO ()) -> Int -> Maybe Manager -> Int -> Int -> IO () -> (((forall a. () => IO a -> IO a) -> IO ()) -> IO ()) -> (Socket -> IO (Socket, SockAddr)) -> Bool -> (IO () -> IO ()) -> ByteString -> Maybe Int -> ProxyProtocol -> Int -> Bool -> (Request -> Status -> Maybe Integer -> IO ()) -> (Request -> ByteString -> Integer -> IO ()) -> Maybe Int -> Int -> Int -> Int -> Maybe ByteString -> Int -> Maybe Counter -> Maybe ServerState -> Bool -> Settings

Files

ChangeLog.md view
@@ -1,5 +1,20 @@ # ChangeLog for warp +## 3.4.21++Requires network 3.2.12.++* `setUnsafeClose` closes connections with network's `unsafeClose` and+  `unsafeGracefulClose`.  Off by default, since a `responseRaw`+  application may leave threads on the socket.+* The listening socket is closed with `unsafeClose` once the accept loop+  has ended.+* Sends use network's `sendAllWith` on every platform, so the timeout+  reaches a send on Windows too.+* An HTTP/2 connection which ends normally is no longer reported to+  `settingsOnException` as http2's `ConnectionIsClosed`; the default+  printed it for every such connection.+ ## 3.4.20  * Building with GHC 9.0 again.
Network/Wai/Handler/Warp.hs view
@@ -80,6 +80,7 @@     setMaxTotalHeaderLength,     setAltSvc,     setMaxBuilderResponseBufferSize,+    setUnsafeClose,      -- ** Getters     getPort,@@ -93,6 +94,7 @@     getGracefulCloseTimeout2,     getOpenConnectionCounter,     getServerState,+    getUnsafeClose,      -- ** Internal server state     --@@ -555,6 +557,14 @@ setMaxBuilderResponseBufferSize :: Int -> Settings -> Settings setMaxBuilderResponseBufferSize maxRspBufSize settings = settings{settingsMaxBuilderResponseBufferSize = maxRspBufSize} +-- | Close connections with network's 'unsafeClose' and+--   'unsafeGracefulClose'.  See 'settingsUnsafeClose' for when it is safe.+--   Default: 'False'.+--+-- @since 3.4.21+setUnsafeClose :: Bool -> Settings -> Settings+setUnsafeClose x y = y{settingsUnsafeClose = x}+ -- | Explicitly pause the slowloris timeout. -- -- This is useful for cases where you partially consume a request body. For@@ -636,6 +646,13 @@ -- @since 3.4.12 getServerState :: Settings -> Maybe ServerState getServerState = settingsServerState++-- | Whether connections are closed with network's 'unsafeClose' and+--   'unsafeGracefulClose'.+--+-- @since 3.4.21+getUnsafeClose :: Settings -> Bool+getUnsafeClose = settingsUnsafeClose  #ifdef MIN_VERSION_crypton_x509 -- | Getting information of client certificate.
Network/Wai/Handler/Warp/HTTP2.hs view
@@ -14,6 +14,7 @@ import Data.IORef (readIORef) import qualified Data.IORef as I import GHC.Conc.Sync (labelThread, myThreadId)+import qualified Network.HTTP2.Client as H2C import qualified Network.HTTP2.Frame as H2 import qualified Network.HTTP2.Server as H2 import Network.Socket (SockAddr)@@ -77,9 +78,15 @@     ok <- checkTLS     setConnHTTP2 conn True     when ok $-        H2.run H2.defaultServerConfig conf $-            http2server "Warp HTTP/2" settings ii transport peersa app+        endedNormally $+            H2.run H2.defaultServerConfig conf $+                http2server "Warp HTTP/2" settings ii transport peersa app   where+    -- http2 ends a connection which has run its course with+    -- 'ConnectionIsClosed', which is no exception to report.+    endedNormally = E.handle $ \e -> case e of+        H2C.ConnectionIsClosed -> return ()+        _ -> E.throwIO e     -- A GOAWAY ends the connection, so there is nothing left to serve     -- on it.     checkTLS = case transport of
Network/Wai/Handler/Warp/Run.hs view
@@ -11,6 +11,8 @@  import Control.Arrow (first) import Control.Concurrent.STM (+    STM,+    retry,     TVar,     atomically,     check,@@ -37,12 +39,13 @@     getSocketName,     isClosedSocketError,     isTransientAcceptError,+    unsafeClose,     withReadable,     setSocketOption,     withSocketsDo,  ) #if MIN_VERSION_network(3,1,1)-import Network.Socket (gracefulClose)+import Network.Socket (gracefulClose, unsafeGracefulClose) #endif import Network.Socket.BufferPool import qualified Network.Socket.ByteString as Sock@@ -92,9 +95,12 @@                         if h2                             then settingsGracefulCloseTimeout2 set                             else settingsGracefulCloseTimeout1 set+                    (closer, gracefulCloser)+                        | settingsUnsafeClose set = (unsafeClose, unsafeGracefulClose)+                        | otherwise = (close, gracefulClose)                 if tm <= 0-                    then close s-                    else gracefulClose s tm `E.catch` throughAsync (return ())+                    then closer s+                    else gracefulCloser s tm `E.catch` throughAsync (return ()) #else             , connClose = close s #endif@@ -135,8 +141,14 @@                     else Nothing             )             E.throwIO-            $ Sock.sendAll s bs+            $ killableSendAll s bs +-- | 'Sock.sendAll' which the timeout can kill.  On Windows a plain send is+-- a foreign call no asynchronous exception reaches; this one waits in STM,+-- and is cancelled if the waiting thread is killed.+killableSendAll :: Socket -> ByteString -> IO ()+killableSendAll s bs = void $ Sock.sendAllWith s bs (retry :: STM ())+ -- | Create a 'Recv' which stops receiving when the server is shutting down -- and no 'Application' is still using this 'Socket'. --@@ -231,7 +243,7 @@             { acceptOrStop = closedAsStopped $ do                 r <- withReadable socket (told stopping) $ settingsAccept set socket                 return $ either (const Nothing) Just r-            , closeListener = close socket+            , closeListener = unsafeClose socket             }   where     told stopping = check =<< readTVar stopping
Network/Wai/Handler/Warp/Settings.hs view
@@ -224,6 +224,15 @@     -- Default: 'Nothing' (warp creates its own internal state)     --     -- @since 3.4.13+    , settingsUnsafeClose :: Bool+    -- ^ Whether to close connections with network's 'unsafeClose' and+    -- 'unsafeGracefulClose', which skip the IO manager.  Use this only if+    -- no thread uses a connection's socket after warp closes it, which+    -- 'responseRaw' applications cannot always promise.+    --+    -- Default: 'False'.+    --+    -- @since 3.4.21     }  -- | Specify usage of the PROXY protocol.@@ -352,6 +361,7 @@         , settingsMaxBuilderResponseBufferSize = 1049000000         , settingsConnectionCounter = Nothing         , settingsServerState = Nothing+        , settingsUnsafeClose = False         }  -- | Create 'defaultSettings' with a connection counter.
test/HTTP2Spec.hs view
@@ -2,6 +2,7 @@  module HTTP2Spec (spec) where +import Control.Concurrent (threadDelay) import Control.Exception (bracket, throwIO) import Data.ByteString (ByteString) import Data.IORef@@ -19,7 +20,16 @@ import Test.Hspec  spec :: Spec-spec = describe "http2server" $+spec = describe "http2server" $ do+    it "reports nothing for a connection the client closes" $ do+        excs <- newIORef []+        let settings = setOnException (\_ e -> modifyIORef' excs (show e :)) defaultSettings+        withApplicationSettings settings (pure hello) $ \port -> do+            get port `shouldReturn` (Just ok200, "hello")+            -- The connection ends once the client has closed it.+            threadDelay 100000+            -- http2's ConnectionIsClosed used to be reported here.+            readIORef excs `shouldReturn` []     it "keeps the response of an application which throws after it" $ do         excs <- newIORef (0 :: Int)         logged <- newIORef []@@ -32,6 +42,9 @@             -- The second response used to go out and be logged, so the             -- log said 500 where the client had been answered 200.             readIORef logged `shouldReturn` [ok200]++hello :: Application+hello _ respond = respond $ responseLBS status200 [] "hello"  -- | Answers, then throws.  The response has gone out by then, so --   nothing can replace it.
test/RunSpec.hs view
@@ -775,6 +775,21 @@             res <- sendGET $ "http://127.0.0.1:" ++ show port             responseBody res `shouldBe` "HelloHelloHelloHello" +    describe "setUnsafeClose" $ do+        let app _ f = f $ responseLBS status200 [("content-length", "6")] "unsafe"+            readAll s = do+                bs <- safeRecv s 4096+                if S.null bs then return [] else (bs :) <$> readAll s+            closes tm =+                withApp (setGracefulCloseTimeout1 tm $ setUnsafeClose True defaultSettings) app $+                    withMySocket $ \ms -> do+                        msWrite ms "GET / HTTP/1.1\r\nHost: localhost\r\nconnection: close\r\n\r\n"+                        bs <- S.concat <$> readAll (msSocket ms)+                        S.takeWhile (/= 13) bs `shouldBe` "HTTP/1.1 200 OK"+                        snd (S.breakSubstring "\r\n\r\n" bs) `shouldBe` "\r\n\r\nunsafe"+        it "closes with unsafeClose" $ closes 0+        it "closes with unsafeGracefulClose" $ closes 1000+     describe "head requests" $ do         let fp = "test/head-response"         let app req f =
test/SendFileSpec.hs view
@@ -10,9 +10,7 @@ import Network.Wai.Handler.Warp.SendFile import Network.Wai.Handler.Warp.Types import System.Directory-import System.Exit import qualified System.IO as IO-import System.Process (system) import Test.Hspec  main :: IO ()@@ -53,11 +51,11 @@      describe "readSendFile" $ do         it "sends a file correctly (1)" $-            tryReadSendFile 10 0 1474 ["foo"] `shouldReturn` ExitSuccess+            tryReadSendFile 10 0 1474 ["foo"] `shouldReturn` True         it "sends a file correctly (2)" $-            tryReadSendFile 10 0 1474 ["012345678", "901234"] `shouldReturn` ExitSuccess+            tryReadSendFile 10 0 1474 ["012345678", "901234"] `shouldReturn` True         it "sends a file correctly (3)" $-            tryReadSendFile 10 20 100 ["012345678", "901234"] `shouldReturn` ExitSuccess+            tryReadSendFile 10 20 100 ["012345678", "901234"] `shouldReturn` True  tryPackHeader :: Int -> [ByteString] -> IO Int tryPackHeader siz hdrs = bracket (allocateBuffer siz) freeBuffer $ \buf ->@@ -77,7 +75,7 @@     send = BS.appendFile outputFile     hook = return () -tryReadSendFile :: Int -> Integer -> Integer -> [ByteString] -> IO ExitCode+tryReadSendFile :: Int -> Integer -> Integer -> [ByteString] -> IO Bool tryReadSendFile siz off len hdrs = bracket setup teardown $ \buf -> do     mapM_ (BS.appendFile expectedFile) hdrs     copyfile inputFile expectedFile off len@@ -105,8 +103,12 @@             return $ bs == bs'         else return $ bs == "" -compareFiles :: FilePath -> FilePath -> IO ExitCode-compareFiles file1 file2 = system $ "cmp -s " ++ file1 ++ " " ++ file2+-- | Whether two files hold the same bytes.+--+-- This used to shell out to @cmp@, which Windows does not have, so these+-- three were the only tests here that could not pass there.+compareFiles :: FilePath -> FilePath -> IO Bool+compareFiles file1 file2 = (==) <$> BS.readFile file1 <*> BS.readFile file2  copyfile :: FilePath -> FilePath -> Integer -> Integer -> IO () copyfile src dst off len =
warp.cabal view
@@ -1,6 +1,6 @@ cabal-version:      >=1.10 name:               warp-version:            3.4.20+version:            3.4.21 license:            MIT license-file:       LICENSE maintainer:         michael@snoyman.com@@ -132,7 +132,7 @@             network-bytestring >=0.1.3 && <0.1.4      else-        build-depends: network >=3.2.10+        build-depends: network >=3.2.12      if flag(warp-debug)         cpp-options: -DWARP_DEBUG