on master help sign in
Add Middleware.Timeout
commit9ffa8fdcb671ade7709111b2d9bb7dd114c9d719 authorpatrick brisbin <pbrisbin@gmail.com> dateMon 30 Jul 2018, 19:33 (8 years ago) parent89f81ce
3 files changed+90
wai-extra/Network/Wai/Middleware/Timeout.hs+31 wai-extra/test/Network/Wai/Middleware/TimeoutSpec.hs+57 wai-extra/wai-extra.cabal+2
wai-extra/Network/Wai/Middleware/Timeout.hsnew file+31
@@ -0,0 +1,31 @@
1+-- | Timeout requests
2+--
3+-- @since X.X.X@
4+--
5+module Network.Wai.Middleware.Timeout
6+ ( timeout
7+ , timeoutStatus
8+ , timeoutAs
9+ ) where
10+
11+import Network.HTTP.Types (Status, status503)
12+import Network.Wai
13+import qualified System.Timeout as Timeout
14+
15+-- | Time out the request after the given number of seconds
16+--
17+-- Timeouts respond with @'status503'@. See @'timeoutStatus'@ or @'timeoutAs'@
18+-- to customize the behavior of the timed-out case.
19+--
20+timeout :: Int -> Middleware
21+timeout = timeoutStatus status503
22+
23+-- | Time out with the given @'Status'@
24+timeoutStatus :: Status -> Int -> Middleware
25+timeoutStatus status = timeoutAs $ responseLBS status [] ""
26+
27+-- | Time out with the given @'Response'@
28+timeoutAs :: Response -> Int -> Middleware
29+timeoutAs timeoutReponse seconds app req respond =
30+ maybe (respond timeoutReponse) pure
31+ =<< Timeout.timeout (seconds * 1000000) (app req respond)
wai-extra/test/Network/Wai/Middleware/TimeoutSpec.hsnew file+57
@@ -0,0 +1,57 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+
3+module Network.Wai.Middleware.TimeoutSpec
4+ ( spec
5+ ) where
6+
7+import Test.Hspec
8+
9+import Control.Concurrent (threadDelay)
10+import Network.HTTP.Types (status200, status503, status504)
11+import Network.Wai
12+import Network.Wai.Middleware.Timeout
13+import Network.Wai.Test
14+
15+spec :: Spec
16+spec = do
17+ describe "timeout" $ do
18+ it "times out slow requests with 503" $ do
19+ let app _req respond = do
20+ threadDelay $ 2 * 1000000
21+ respond $ responseLBS status200 [] ""
22+
23+ resp <- runApp $ timeout 1 app
24+
25+ simpleStatus resp `shouldBe` status503
26+
27+ it "does not time out fast requests" $ do
28+ let app _req respond = respond $ responseLBS status200 [] ""
29+
30+ resp <- runApp $ timeout 3 app
31+
32+ simpleStatus resp `shouldBe` status200
33+
34+ describe "timeoutStatus" $ do
35+ it "allows customizing the timeout response status" $ do
36+ let app _req respond = do
37+ threadDelay $ 2 * 1000000
38+ respond $ responseLBS status200 [] ""
39+
40+ resp <- runApp $ timeoutStatus status504 1 app
41+
42+ simpleStatus resp `shouldBe` status504
43+
44+ describe "timeoutAs" $ do
45+ it "allows customizing the timeout response" $ do
46+ let app _req respond = do
47+ threadDelay $ 2 * 1000000
48+ respond $ responseLBS status200 [] ""
49+ timeoutResponse = responseLBS status503 [("X-Timeout", "1")] ""
50+
51+ resp <- runApp $ timeoutAs timeoutResponse 1 app
52+
53+ simpleStatus resp `shouldBe` status503
54+ simpleHeaders resp `shouldBe` [("X-Timeout", "1")]
55+
56+runApp :: Application -> IO SResponse
57+runApp = runSession $ request defaultRequest
wai-extra/wai-extra.cabal+2
@@ -148,6 +148,7 @@ Library
148148 Network.Wai.Middleware.ForceDomain
149149 Network.Wai.Middleware.ForceSSL
150150 Network.Wai.Middleware.Routed
151+ Network.Wai.Middleware.Timeout
151152 Network.Wai.Parse
152153 Network.Wai.Request
153154 Network.Wai.UrlMap
@@ -186,6 +187,7 @@ test-suite spec
186187 Network.Wai.Middleware.ForceSSLSpec
187188 Network.Wai.Middleware.RoutedSpec
188189 Network.Wai.Middleware.StripHeadersSpec
190+ Network.Wai.Middleware.TimeoutSpec
189191 WaiExtraSpec
190192 build-depends: base >= 4 && < 5
191193 , wai-extra