on 08265cc help sign in
46 files changed+279−443
since splitsnapshots
unifiedsplit
.azure/azure-linux-template.yml+22−8 .azure/azure-osx-template.yml+12−2 .azure/azure-windows-template.yml+3−4 .gitignore−1 stack-lts-11.yaml+6−3 stack-lts-12.yaml+6−3 stack-lts-6.yaml+35 stack-lts-9.yaml+31 stack-nightly.yaml−20 stack.yaml+7−3 wai-app-static/ChangeLog.md−10 wai-app-static/Network/Wai/Application/Static.hs+8−10 wai-app-static/WaiAppStatic/CmdLine.hs−1 wai-app-static/WaiAppStatic/Listing.hs+1−1 wai-app-static/WaiAppStatic/Storage/Embedded/TH.hs+1 wai-app-static/WaiAppStatic/Types.hs−2 wai-app-static/test/WaiAppStaticTest.hs+8−8 wai-app-static/wai-app-static.cabal+1−1 wai-conduit/Network/Wai/Conduit.hs+6−5 wai-extra/ChangeLog.md−8 wai-extra/Network/Wai/EventSource.hs+1−2 wai-extra/Network/Wai/Test.hs+14−22 wai-extra/example/Main.hs+2−2 wai-extra/test/Network/Wai/TestSpec.hs+11−41 wai-extra/wai-extra.cabal+1−1 wai-websockets/server.lhs−6 wai-websockets/wai-websockets.cabal−1 warp-tls/ChangeLog.md−14 warp-tls/Network/Wai/Handler/WarpTLS.hs+16−21 warp-tls/warp-tls.cabal+5−5 warp/ChangeLog.md+1−31 warp/Network/Wai/Handler/Warp.hs−50 warp/Network/Wai/Handler/Warp/File.hs+4−7 warp/Network/Wai/Handler/Warp/HTTP2.hs+3−3 warp/Network/Wai/Handler/Warp/HTTP2/Request.hs+1−2 warp/Network/Wai/Handler/Warp/HTTP2/Response.hs+1−2 warp/Network/Wai/Handler/Warp/Header.hs−2 warp/Network/Wai/Handler/Warp/Recv.hs+1−13 warp/Network/Wai/Handler/Warp/Request.hs+17−18 warp/Network/Wai/Handler/Warp/Response.hs+16−19 warp/Network/Wai/Handler/Warp/Run.hs+24−34 warp/Network/Wai/Handler/Warp/Settings.hs+5−31 warp/Network/Wai/Handler/Warp/Types.hs−10 warp/test/FileSpec.hs+1−1 warp/test/RequestSpec.hs+7−11 warp/warp.cabal+1−4
.azure/azure-linux-template.yml+22−8
@@ -5,6 +5,16 @@ jobs:
55 vmImage: ${{ parameters.vmImage }}
66 strategy:
77 matrix:
8+ stack-def:
9+ BUILD: stack
10+ stack-lts-6:
11+ BUILD: stack
12+ STACK_YAML: stack-lts-6.yaml
13+ ARGS: "--resolver lts-6"
14+ stack-lts-9:
15+ BUILD: stack
16+ STACK_YAML: stack-lts-9.yaml
17+ ARGS: "--resolver lts-9"
818 stack-lts-11:
919 BUILD: stack
1020 STACK_YAML: stack-lts-11.yaml
@@ -13,13 +23,17 @@ jobs:
1323 BUILD: stack
1424 STACK_YAML: stack-lts-12.yaml
1525 ARGS: "--resolver lts-12"
16− stack-lts-14:
26+ stack-lts-13:
1727 BUILD: stack
18− ARGS: "--resolver lts-14"
19− stack-nightly:
20− BUILD: stack
21− STACK_YAML: stack-nightly.yaml
22− ARGS: "--resolver nightly"
28+ ARGS: "--resolver lts-13"
29+ cabal-7.10.3:
30+ BUILD: cabal
31+ GHCVER: 7.10.3
32+ CABALVER: 1.22
33+ cabal-8.0.2:
34+ BUILD: cabal
35+ GHCVER: 8.0.2
36+ CABALVER: 1.24
2337 cabal-8.2.2:
2438 BUILD: cabal
2539 GHCVER: 8.4.4
@@ -28,9 +42,9 @@ jobs:
2842 BUILD: cabal
2943 GHCVER: 8.4.4
3044 CABALVER: 2.2
31− cabal-8.6.5:
45+ cabal-8.6.4:
3246 BUILD: cabal
33− GHCVER: 8.6.5
47+ GHCVER: 8.6.4
3448 CABALVER: 2.4
3549 maxParallel: 6
3650 steps:
.azure/azure-osx-template.yml+12−2
@@ -5,6 +5,16 @@ jobs:
55 vmImage: ${{ parameters.vmImage }}
66 strategy:
77 matrix:
8+ stack-def:
9+ BUILD: stack
10+ stack-lts-6:
11+ BUILD: stack
12+ STACK_YAML: stack-lts-6.yaml
13+ ARGS: "--resolver lts-6"
14+ stack-lts-9:
15+ BUILD: stack
16+ STACK_YAML: stack-lts-9.yaml
17+ ARGS: "--resolver lts-9"
818 stack-lts-11:
919 BUILD: stack
1020 STACK_YAML: stack-lts-11.yaml
@@ -13,9 +23,9 @@ jobs:
1323 BUILD: stack
1424 STACK_YAML: stack-lts-12.yaml
1525 ARGS: "--resolver lts-12"
16− stack-lts-14:
26+ stack-lts-13:
1727 BUILD: stack
18− ARGS: "--resolver lts-14"
28+ ARGS: "--resolver lts-13"
1929 maxParallel: 3
2030 steps:
2131 - script: |
.azure/azure-windows-template.yml+3−4
@@ -5,9 +5,9 @@ jobs:
55 vmImage: ${{ parameters.vmImage }}
66 strategy:
77 matrix:
8− stack-lts-14:
8+ stack-lts-13:
99 BUILD: stack
10− ARGS: "--resolver lts-14"
10+ ARGS: "--resolver lts-13"
1111 maxParallel: 3
1212 steps:
1313 - bash: |
@@ -16,8 +16,7 @@ jobs:
1616 unzip -o /usr/bin/stack.zip -d /usr/bin/
1717 stack setup $ARGS > /dev/null
1818 stack --install-ghc $ARGS test --bench --only-dependencies
19− stack $ARGS test --bench --no-run-benchmarks --no-run-tests
20− stack $ARGS test --bench --no-run-benchmarks --jobs 1 # non-parallel test execution
19+ stack $ARGS test --bench --no-run-benchmarks
2120 env:
2221 OS_NAME: ${{ parameters.os }}
2322 displayName: 'Installation ${{parameters.os}} & Test'
.gitignore−1
@@ -9,4 +9,3 @@ tarballs/
99cabal.sandbox.config
1010.stack-work/
1111*~
12−stack*.yaml.lock
stack-lts-11.yaml+6−3
@@ -17,11 +17,14 @@ extra-deps:
1717- streaming-commons-0.2.1.0@sha256:163af02944f374f316e35257c1afbffefd2c2852a85a151d1ea0ad22152cf28d,4990
1818- http2-2.0.0
1919- network-byte-order-0.1.1.0
20−- tls-1.5.3
21−- tls-session-manager-0.0.4
22−- x509-1.7.5
2320nix:
2421 enable: false
2522 packages:
2623 - fcgi
2724 - zlib
25+image:
26+ containers:
27+ - base: "fpco/pid1"
28+ name: "yesodweb/warp"
29+ executables:
30+ - warp
stack-lts-12.yaml+6−3
@@ -18,9 +18,12 @@ nix:
1818 packages:
1919 - fcgi
2020 - zlib
21+image:
22+ containers:
23+ - base: "fpco/pid1"
24+ name: "yesodweb/warp"
25+ executables:
26+ - warp
2127extra-deps:
2228- http2-2.0.0
2329- network-byte-order-0.1.1.0
24−- tls-1.5.3
25−- tls-session-manager-0.0.4
26−- x509-1.7.5
stack-lts-6.yamlnew file+35
@@ -0,0 +1,35 @@
1+resolver: lts-6.35
2+packages:
3+- ./auto-update
4+- ./mime-types
5+- ./wai
6+- ./wai-extra
7+- ./warp
8+- ./warp-tls
9+- ./wai-app-static
10+- ./wai-websockets
11+- ./wai-conduit
12+- ./time-manager
13+extra-deps:
14+- bsb-http-chunked-0.0.0.2@sha256:0571ef33ec5530104503d32eaf24f2d7c221f350e5fc475a6dd8e84311bc0ca1,1792
15+- streaming-commons-0.2.1.0@sha256:163af02944f374f316e35257c1afbffefd2c2852a85a151d1ea0ad22152cf28d,4990
16+- tls-session-manager-0.0.0.2@sha256:e3d3f8a026196df46746a19d3d7d31211b2fca3aefed9074e951b2dcc1b8833c,872
17+- wai-logger-2.3.2@sha256:7f5dbc72c0753bd3e0e73f8f542d9d159d1d70f8ff3a3ec16d0b74b500534fc6,1572
18+- gauge-0.2.3@sha256:ce41cb66ebf730a5050181db0338b1a4b3f76ac71331bf5070089bcd4352ff46,3777
19+- psqueues-0.2.7.0@sha256:189970837d0aae01f48cd2a8aac6ce314191939e118cc0488aee1fb12da1956a,4757
20+- basement-0.0.7@rev:0
21+- http-client-0.5.13.1@rev:0
22+- http-types-0.12.3@rev:0
23+- http2-2.0.0
24+- network-byte-order-0.1.1.0
25+nix:
26+ enable: false
27+ packages:
28+ - fcgi
29+ - zlib
30+image:
31+ containers:
32+ - base: "fpco/pid1"
33+ name: "yesodweb/warp"
34+ executables:
35+ - warp
stack-lts-9.yamlnew file+31
@@ -0,0 +1,31 @@
1+resolver: lts-9.21
2+packages:
3+- ./auto-update
4+- ./mime-types
5+- ./wai
6+- ./wai-extra
7+- ./warp
8+- ./warp-tls
9+- ./wai-app-static
10+- ./wai-websockets
11+- ./wai-conduit
12+- ./time-manager
13+extra-deps:
14+- bsb-http-chunked-0.0.0.2@sha256:0571ef33ec5530104503d32eaf24f2d7c221f350e5fc475a6dd8e84311bc0ca1,1792
15+- streaming-commons-0.2.1.0@sha256:163af02944f374f316e35257c1afbffefd2c2852a85a151d1ea0ad22152cf28d,4990
16+- wai-logger-2.3.2@sha256:7f5dbc72c0753bd3e0e73f8f542d9d159d1d70f8ff3a3ec16d0b74b500534fc6,1572
17+- http-client-0.5.13.1@rev:0
18+- http-types-0.12.3@rev:0
19+- http2-2.0.0
20+- network-byte-order-0.1.1.0
21+nix:
22+ enable: false
23+ packages:
24+ - fcgi
25+ - zlib
26+image:
27+ containers:
28+ - base: "fpco/pid1"
29+ name: "yesodweb/warp"
30+ executables:
31+ - warp
stack-nightly.yamldeleted−20
@@ -1,20 +0,0 @@
1−resolver: nightly-2020-01-08
2−packages:
3−- ./auto-update
4−- ./mime-types
5−- ./wai
6−- ./wai-extra
7−- ./warp
8−- ./warp-tls
9−- ./wai-app-static
10−- ./wai-websockets
11−- ./wai-conduit
12−- ./time-manager
13−flags:
14− wai-extra:
15− build-example: true
16−nix:
17− enable: false
18− packages:
19− - fcgi
20− - zlib
stack.yaml+7−3
@@ -1,4 +1,4 @@
1−resolver: lts-14.22
1+resolver: lts-13.14
22packages:
33- ./auto-update
44- ./mime-types
@@ -18,8 +18,12 @@ nix:
1818 packages:
1919 - fcgi
2020 - zlib
21+image:
22+ containers:
23+ - base: "fpco/pid1"
24+ name: "yesodweb/warp"
25+ executables:
26+ - warp
2127extra-deps:
2228- http2-2.0.0
2329- network-byte-order-0.1.1.0
24−- tls-1.5.3
25−- tls-session-manager-0.0.4
wai-app-static/ChangeLog.md−10
@@ -1,13 +1,3 @@
1−# wai-app-static changelog
2−
3−## 3.1.7.1
4−
5−* Update the test suite too
6−
7−## 3.1.7
8−
9−* Use 302 instead of 301 redirect, to avoid caching the presence of an index.html file
10−
111## 3.1.6.3
122
133* The executable warp obeys `-h` option properly for host
wai-app-static/Network/Wai/Application/Static.hs+8−10
@@ -164,13 +164,11 @@ serveFile StaticSettings {..} req file
164164 -- Didn't match, but we have a hash value. Send the file contents
165165 -- with an ETag header.
166166 --
167− -- RFC7232 (HTTP 1.1):
168− -- > A recipient MUST ignore If-Modified-Since if the request contains an
169− -- > If-None-Match header field; the condition in If-None-Match is
170− -- > considered to be a more accurate replacement for the condition in
171− -- > If-Modified-Since, and the two are only combined for the sake of
172− -- > interoperating with older intermediaries that might not implement
173− -- > If-None-Match.
167+ -- Note: It would be arguably better to next check
168+ -- if-modified-since and return a 304 if that indicates a match as
169+ -- well. However, the circumstances under which such a situation
170+ -- could arise would be very anomalous, and should likely warrant a
171+ -- new file being sent anyway.
174172 (Just hash, _) -> respond [("ETag", hash)]
175173
176174 -- No hash value available, fall back to last modified support.
@@ -245,7 +243,7 @@ staticAppPieces ss rawPieces req sendResponse = liftIO $ do
245243 response :: StaticResponse -> IO W.ResponseReceived
246244 response (FileResponse file ch) = do
247245 mimetype <- ssGetMimeType ss file
248− -- let filesize = fileGetSize file
246+ let filesize = fileGetSize file
249247 let headers = ("Content-Type", mimetype)
250248 -- Let Warp provide the content-length, since it takes
251249 -- range requests into account
@@ -269,13 +267,13 @@ staticAppPieces ss rawPieces req sendResponse = liftIO $ do
269267 Just hash -> replace "etag" (Just hash) (W.queryString req)
270268 Nothing -> remove "etag" (W.queryString req)
271269
272− sendResponse $ W.responseLBS H.status302
270+ sendResponse $ W.responseLBS H.status301
273271 [ ("Content-Type", "text/plain")
274272 , ("Location", S8.append loc $ H.renderQuery True qString)
275273 ] "Redirect"
276274
277275 response (RawRedirect path) =
278− sendResponse $ W.responseLBS H.status302
276+ sendResponse $ W.responseLBS H.status301
279277 [ ("Content-Type", "text/plain")
280278 , ("Location", path)
281279 ] "Redirect"
wai-app-static/WaiAppStatic/CmdLine.hs−1
@@ -39,7 +39,6 @@ data Args = Args
3939 }
4040
4141#if MIN_VERSION_optparse_applicative(0, 10, 0)
42−option' :: Mod OptionFields Int -> Parser Int
4342option' = option auto
4443#else
4544option' = option
wai-app-static/WaiAppStatic/Listing.hs+1−1
@@ -64,7 +64,7 @@ defaultListing pieces (Folder contents) = do
6464
6565 -- Add a link to the root of the tree
6666 showFolder' :: Bool -> Pieces -> H.Html
67− showFolder' hasTrailingSlash pieces' = showFolder hasTrailingSlash (unsafeToPiece "root" : pieces')
67+ showFolder' hasTrailingSlash pieces = showFolder hasTrailingSlash (unsafeToPiece "root" : pieces)
6868
6969 showFolder :: Bool -> Pieces -> H.Html
7070 showFolder _ [] = "/" -- won't happen
wai-app-static/WaiAppStatic/Storage/Embedded/TH.hs+1
@@ -7,6 +7,7 @@ module WaiAppStatic.Storage.Embedded.TH(
77
88import Data.ByteString.Builder.Extra (byteStringInsert)
99import Codec.Compression.GZip (compress)
10+import Control.Applicative
1011import Data.ByteString.Unsafe (unsafePackAddressLen)
1112import Data.Either (lefts, rights)
1213import GHC.Exts (Int(..))
wai-app-static/WaiAppStatic/Types.hs−2
@@ -59,8 +59,6 @@ toPieces :: [Text] -> Maybe Pieces
5959toPieces = mapM toPiece
6060
6161-- | Request coming from a user. Corresponds to @pathInfo@.
62−--
63−-- The root path is the empty list.
6462type Pieces = [Piece]
6563
6664-- | Values for the max-age component of the cache-control response header.
wai-app-static/test/WaiAppStaticTest.hs+8−8
@@ -61,18 +61,18 @@ spec = do
6161 assertStatus 404 =<<
6262 request (setRawPathInfo defRequest "doesNotExist")
6363
64− it "302 redirect when multiple slashes" $ webApp $ do
64+ it "301 redirect when multiple slashes" $ webApp $ do
6565 req <- request (setRawPathInfo defRequest "a//b/c")
66− assertStatus 302 req
66+ assertStatus 301 req
6767 assertHeader "Location" "../../a/b/c" req
6868
6969 let absoluteApp = flip runSession $ staticApp $ (defaultWebAppSettings "test") {
7070 ssMkRedirect = \_ u -> S8.append "http://www.example.com" u
7171 }
72− it "302 redirect when multiple slashes" $ absoluteApp $
72+ it "301 redirect when multiple slashes" $ absoluteApp $
7373 flip mapM_ ["/a//b/c", "a//b/c"] $ \path -> do
7474 req <- request (setRawPathInfo defRequest path)
75− assertStatus 302 req
75+ assertStatus 301 req
7676 assertHeader "Location" "http://www.example.com/a/b/c" req
7777
7878 describe "webApp when requesting a static asset" $ do
@@ -131,10 +131,10 @@ spec = do
131131 assertStatus 304 req
132132 assertNoHeader "Cache-Control" req
133133
134− context "302 redirect to add a trailing slash on directories if missing" $ do
134+ context "301 redirect to add a trailing slash on directories if missing" $ do
135135 it "works at the root" $ fileServerApp $ do
136136 req <- request (setRawPathInfo defRequest "/a")
137− assertStatus 302 req
137+ assertStatus 301 req
138138 assertHeader "Location" "/a/" req
139139
140140 it "works when an index.html is delivered" $ do
@@ -144,7 +144,7 @@ spec = do
144144 inTempDirectory $ fileServerAppWithSettings settings $ do
145145 liftIO $ touch "foo/index.html"
146146 req <- request (setRawPathInfo defRequest "/foo")
147− assertStatus 302 req
147+ assertStatus 301 req
148148 assertHeader "Location" "/foo/" req
149149
150150 let urlMapApp = flip runSession $ \req send ->
@@ -158,7 +158,7 @@ spec = do
158158 "urlMapApp: only works at subPath"
159159 it "works with subpath at the root of the file server" $ urlMapApp $ do
160160 req <- request (setRawPathInfo defRequest "/subPath")
161− assertStatus 302 req
161+ assertStatus 301 req
162162 assertHeader "Location" "/subPath/" req
163163
164164 context "with defaultWebAppSettings" $ do
wai-app-static/wai-app-static.cabal+1−1
@@ -1,5 +1,5 @@
11name: wai-app-static
2−version: 3.1.7.1
2+version: 3.1.6.3
33license: MIT
44license-file: LICENSE
55author: Michael Snoyman <michael@snoyman.com>
wai-conduit/Network/Wai/Conduit.hs+6−5
@@ -17,16 +17,17 @@ import qualified Data.ByteString as S
1717import Control.Monad (unless)
1818import Network.HTTP.Types
1919import Data.ByteString.Builder (Builder)
20+import Data.IORef
2021import qualified Data.Conduit.List as CL
2122
2223-- | Stream the request body.
2324--
2425-- Since 3.0.0
25−sourceRequestBody :: MonadIO m => Request -> ConduitT () ByteString m ()
26+sourceRequestBody :: MonadIO m => Request -> Source m ByteString
2627sourceRequestBody req =
2728 loop
2829 where
29− go = liftIO (getRequestBodyChunk req)
30+ go = liftIO (requestBody req)
3031
3132 loop = do
3233 bs <- go
@@ -37,9 +38,9 @@ sourceRequestBody req =
3738-- | Create an HTTP response out of a @Source@.
3839--
3940-- Since 3.0.0
40−responseSource :: Status -> ResponseHeaders -> ConduitT () (Flush Builder) IO () -> Response
41+responseSource :: Status -> ResponseHeaders -> Source IO (Flush Builder) -> Response
4142responseSource s hs src = responseStream s hs $ \send flush ->
42− runConduit $ src .| CL.mapM_ (\mbuilder ->
43+ src $$ CL.mapM_ (\mbuilder ->
4344 case mbuilder of
4445 Chunk b -> send b
4546 Flush -> flush)
@@ -49,7 +50,7 @@ responseSource s hs src = responseStream s hs $ \send flush ->
4950--
5051-- Since 3.0.0
5152responseRawSource :: (MonadIO m, MonadIO n)
52− => (ConduitT () ByteString m () -> ConduitT ByteString Void n () -> IO ())
53+ => (Source m ByteString -> Sink ByteString n () -> IO ())
5354 -> Response
5455 -> Response
5556responseRawSource app =
wai-extra/ChangeLog.md−8
@@ -1,13 +1,5 @@
11# Changelog for wai-extra
22
3−## 3.0.29.1
4−
5−* Fix `Network.Wai.Test.request` always sending an empty request body [#794](https://github.com/yesodweb/wai/pull/794)
6−
7−## 3.0.29
8−
9−* Export `Network.Wai.EventSource.eventStreamAppRaw` [#786](https://github.com/yesodweb/wai/pull/786)
10−
113## 3.0.28
124
135* Add `Network.Wai.EventSource.eventStreamAppRaw` [#767](https://github.com/yesodweb/wai/pull/767)
wai-extra/Network/Wai/EventSource.hs+1−2
@@ -11,8 +11,7 @@
1111module Network.Wai.EventSource (
1212 ServerEvent(..),
1313 eventSourceAppChan,
14− eventSourceAppIO,
15− eventStreamAppRaw
14+ eventSourceAppIO
1615 ) where
1716
1817import Data.Function (fix)
wai-extra/Network/Wai/Test.hs+14−22
@@ -99,10 +99,6 @@ runSession session app = ST.evalStateT (runReaderT session app) initState
9999data SRequest = SRequest
100100 { simpleRequest :: Request
101101 , simpleRequestBody :: L.ByteString
102− -- ^ Request body that will override the one set in 'simpleRequest'.
103− --
104− -- This is usually simpler than setting the body as a stateful IO-action
105− -- in 'simpleRequest'.
106102 }
107103data SResponse = SResponse
108104 { simpleStatus :: H.Status
@@ -110,16 +106,8 @@ data SResponse = SResponse
110106 , simpleBody :: L.ByteString
111107 }
112108 deriving (Show, Eq)
113−
114109request :: Request -> Session SResponse
115−request req = do
116− app <- ask
117− req' <- addCookiesToRequest req
118− response <- liftIO $ do
119− ref <- newIORef $ error "runResponse gave no result"
120− ResponseReceived <- app req' (runResponse ref)
121− readIORef ref
122− extractSetCookieFromSResponse response
110+request = srequest . flip SRequest L.empty
123111
124112-- | Set whole path (request path + query string).
125113setPath :: Request -> S8.ByteString -> Request
@@ -178,18 +166,22 @@ extractSetCookieFromSResponse response = do
178166 (Map.fromList [(Cookie.setCookieName c, c) | c <- newClientCookies ]))
179167 return response
180168
181−-- | Similar to 'request', but allows setting the request body as a plain
182−-- 'L.ByteString'.
183169srequest :: SRequest -> Session SResponse
184170srequest (SRequest req bod) = do
171+ app <- ask
185172 refChunks <- liftIO $ newIORef $ L.toChunks bod
186− request $
187− req
188− { requestBody = atomicModifyIORef refChunks $ \bss ->
189− case bss of
190− [] -> ([], S.empty)
191− x:y -> (y, x)
192− }
173+ let req' = req
174+ { requestBody = atomicModifyIORef refChunks $ \bss ->
175+ case bss of
176+ [] -> ([], S.empty)
177+ x:y -> (y, x)
178+ }
179+ req'' <- addCookiesToRequest req'
180+ response <- liftIO $ do
181+ ref <- newIORef $ error "runResponse gave no result"
182+ ResponseReceived <- app req'' (runResponse ref)
183+ readIORef ref
184+ extractSetCookieFromSResponse response
193185
194186runResponse :: IORef SResponse -> Response -> IO ResponseReceived
195187runResponse ref res = do
wai-extra/example/Main.hs+2−2
@@ -42,10 +42,10 @@ eventRaw = handle 0
4242 where
4343 handle counter emit flush = do
4444 threadDelay 1000000
45− _ <- emit $ ServerEvent (Just $ string8 "raw")
45+ emit $ ServerEvent (Just $ string8 "raw")
4646 Nothing
4747 [string8 . show $ counter]
48− _ <- flush
48+ flush
4949 handle (counter + 1) emit flush
5050
5151main :: IO ()
wai-extra/test/Network/Wai/TestSpec.hs+11−41
@@ -3,8 +3,6 @@ module Network.Wai.TestSpec (main, spec) where
33
44import Control.Monad (void)
55
6−import qualified Data.IORef as IORef
7−
86import qualified Data.Text.Encoding as TE
97
108import Data.Time.Calendar (fromGregorian)
@@ -55,53 +53,25 @@ spec = do
5553 it "sets rawQueryString to empty string" $ do
5654 rawQueryString (setPath defaultRequest "/foo/bar/baz") `shouldBe` ""
5755
58− describe "srequest" $ do
59−
60− let echoApp req respond = do
61− reqBody <- L8.fromStrict <$> getRequestBodyChunk req
62− let reqHeaders = requestHeaders req
63− respond $
64− responseLBS
65− status200
66− reqHeaders
67− reqBody
68−
69− it "returns the response body of an echo app" $ do
70− sresp <- flip runSession echoApp $
71− srequest $ SRequest defaultRequest "request body"
72− simpleBody sresp `shouldBe` "request body"
73−
7456 describe "request" $ do
7557
76− let echoApp req respond = do
77− reqBody <- L8.fromStrict <$> getRequestBodyChunk req
78− let reqHeaders = requestHeaders req
58+ let simpleApp _req respond =
7959 respond $
8060 responseLBS
8161 status200
82− reqHeaders
83− reqBody
62+ [("foo", "bar")]
63+ "simple"
8464
85− it "returns the status code of an echo app on default request" $ do
86− sresp <- runSession (request defaultRequest) echoApp
65+ it "returns the status code of a simple app on default request" $ do
66+ sresp <- runSession (request defaultRequest) simpleApp
8767 simpleStatus sresp `shouldBe` status200
8868
89− it "returns the response body of an echo app" $ do
90− bodyRef <- IORef.newIORef "request body"
91− let getBodyChunk = IORef.atomicModifyIORef bodyRef $ \leftover -> ("", leftover)
92− sresp <- flip runSession echoApp $
93− request $
94− defaultRequest
95− { requestBody = getBodyChunk
96− }
97− simpleBody sresp `shouldBe` "request body"
98−
99− it "returns the response headers of an echo app" $ do
100− sresp <- flip runSession echoApp $
101− request $
102− defaultRequest
103− { requestHeaders = [("foo", "bar")]
104− }
69+ it "returns the response body of a simple app on default request" $ do
70+ sresp <- runSession (request defaultRequest) simpleApp
71+ simpleBody sresp `shouldBe` "simple"
72+
73+ it "returns the response headers of a simple app on default request" $ do
74+ sresp <- runSession (request defaultRequest) simpleApp
10575 simpleHeaders sresp `shouldBe` [("foo", "bar")]
10676
10777 let cookieApp req respond =
wai-extra/wai-extra.cabal+1−1
@@ -1,5 +1,5 @@
11Name: wai-extra
2−Version: 3.0.29.1
2+Version: 3.0.28
33Synopsis: Provides some basic WAI handlers and middleware.
44description:
55 Provides basic WAI handler and middleware functionality:
wai-websockets/server.lhs−6
@@ -8,8 +8,6 @@ this example, keep the [reference](http://jaspervdj.be/websockets/reference)
88nearby to check out the functions we use.
99
1010> {-# LANGUAGE OverloadedStrings, TemplateHaskell #-}
11−> {-# LANGUAGE CPP #-}
12−> {-# OPTIONS_GHC -Wno-unused-top-binds #-} -- for numClients
1311> import Data.Char (isPunctuation, isSpace)
1412> import Data.Monoid (mappend)
1513> import Data.Text (Text)
@@ -101,11 +99,7 @@ stays alive on some browsers.
10199
102100> application state pending = do
103101> conn <- WS.acceptRequest pending
104−#if __GLASGOW_HASKELL__ >= 806
105−> WS.withPingThread conn 30 (return ()) $ do
106−#else
107102> WS.forkPingThread conn 30
108−#endif
109103
110104When a client is successfully connected, we read the first message. This should
111105be in the format of "Hi! I am Jasper", where Jasper is the requested username.
wai-websockets/wai-websockets.cabal−1
@@ -45,7 +45,6 @@ Executable wai-websockets-example
4545 , text
4646 , file-embed
4747 , http-types
48− other-modules: Network.Wai.Handler.WebSockets
4948 else
5049 buildable: False
5150
warp-tls/ChangeLog.md−14
@@ -1,17 +1,3 @@
1−## 3.2.11
2−
3−* Ignoring an exception from shutdown (gracefulClose).
4−
5−## 3.2.10
6−
7−* Passing client certificate, if any, to Warp
8− [#783](https://github.com/yesodweb/wai/pull/783)
9−
10−## 3.2.9
11−
12−* Cooperating setGracefulCloseTimeout1 and setGracefulCloseTimeout2 of Warp.
13− [#782](https://github.com/yesodweb/wai/pull/782)
14−
151## 3.2.8
162
173* Using gracefullClose of network 3.1.1 or later if available.
warp-tls/Network/Wai/Handler/WarpTLS.hs+16−21
@@ -281,7 +281,7 @@ runTLSSocket' :: TLSSettings -> Settings -> TLS.Credential -> TLS.SessionManager
281281runTLSSocket' tlsset@TLSSettings{..} set credential mgr sock app =
282282 runSettingsConnectionMakerSecure set get app
283283 where
284− get = getter tlsset set sock params
284+ get = getter tlsset sock params
285285 params = def { -- TLS.ServerParams
286286 TLS.serverWantClientCert = tlsWantClientCert
287287 , TLS.serverCACertificates = []
@@ -322,46 +322,44 @@ alpn xs
322322
323323----------------------------------------------------------------
324324
325−getter :: TLS.TLSParams params => TLSSettings -> Settings -> Socket -> params -> IO (IO (Connection, Transport), SockAddr)
326−getter tlsset@TLSSettings{..} set sock params = do
325+getter :: TLS.TLSParams params => TLSSettings -> Socket -> params -> IO (IO (Connection, Transport), SockAddr)
326+getter tlsset@TLSSettings{..} sock params = do
327327#if WINDOWS
328328 (s, sa) <- windowsThreadBlockHack $ accept sock
329329#else
330330 (s, sa) <- accept sock
331331#endif
332332 setSocketCloseOnExec s
333− return (mkConn tlsset set s params, sa)
333+ return (mkConn tlsset s params, sa)
334334
335−mkConn :: TLS.TLSParams params => TLSSettings -> Settings -> Socket -> params -> IO (Connection, Transport)
336−mkConn tlsset set s params = switch `onException` close s
335+mkConn :: TLS.TLSParams params => TLSSettings -> Socket -> params -> IO (Connection, Transport)
336+mkConn tlsset s params = switch `onException` close s
337337 where
338338 switch = do
339339 firstBS <- safeRecv s 4096
340340 if not (S.null firstBS) && S.head firstBS == 0x16 then
341− httpOverTls tlsset set s firstBS params
341+ httpOverTls tlsset s firstBS params
342342 else
343− plainHTTP tlsset set s firstBS
343+ plainHTTP tlsset s firstBS
344344
345345----------------------------------------------------------------
346346
347−httpOverTls :: TLS.TLSParams params => TLSSettings -> Settings -> Socket -> S.ByteString -> params -> IO (Connection, Transport)
348−httpOverTls TLSSettings{..} _set s bs0 params = do
347+httpOverTls :: TLS.TLSParams params => TLSSettings -> Socket -> S.ByteString -> params -> IO (Connection, Transport)
348+httpOverTls TLSSettings{..} s bs0 params = do
349349 recvN <- makePlainReceiveN s bs0
350350 ctx <- TLS.contextNew (backend recvN) params
351351 TLS.contextHookSetLogging ctx tlsLogging
352352 TLS.handshake ctx
353− h2 <- (== Just "h2") <$> TLS.getNegotiatedProtocol ctx
354− isH2 <- I.newIORef h2
355353 writeBuf <- allocateBuffer bufferSize
356354 -- Creating a cache for leftover input data.
357355 ref <- I.newIORef ""
358356 tls <- getTLSinfo ctx
359− return (conn ctx writeBuf ref isH2, tls)
357+ return (conn ctx writeBuf ref, tls)
360358 where
361359 backend recvN = TLS.Backend {
362360 TLS.backendFlush = return ()
363361#if MIN_VERSION_network(3,1,1)
364− , TLS.backendClose = gracefulClose s 5000 `E.catch` \(SomeException _) -> return ()
362+ , TLS.backendClose = gracefulClose s 5000
365363#else
366364 , TLS.backendClose = close s
367365#endif
@@ -370,7 +368,7 @@ httpOverTls TLSSettings{..} _set s bs0 params = do
370368 }
371369 sendAll' sock bs = sendAll sock bs `E.catch` \(SomeException _) ->
372370 throwIO ConnectionClosedByPeer
373− conn ctx writeBuf ref isH2 = Connection {
371+ conn ctx writeBuf ref = Connection {
374372 connSendMany = TLS.sendData ctx . L.fromChunks
375373 , connSendAll = sendall
376374 , connSendFile = sendfile
@@ -380,7 +378,6 @@ httpOverTls TLSSettings{..} _set s bs0 params = do
380378 , connRecvBuf = recvBuf ref
381379 , connWriteBuffer = writeBuf
382380 , connBufferSize = bufferSize
383− , connHTTP2 = isH2
384381 }
385382 where
386383 sendall = TLS.sendData ctx . L.fromChunks . return
@@ -468,13 +465,11 @@ getTLSinfo ctx = do
468465#if MIN_VERSION_tls(1,5,0)
469466 TLS.TLS13 -> (3,4)
470467#endif
471− clientCert <- TLS.getClientCertificateChain ctx
472468 return TLS {
473469 tlsMajorVersion = major
474470 , tlsMinorVersion = minor
475471 , tlsNegotiatedProtocol = proto
476472 , tlsChiperID = TLS.cipherID infoCipher
477− , tlsClientCertificate = clientCert
478473 }
479474
480475tryIO :: IO a -> IO (Either IOException a)
@@ -482,10 +477,10 @@ tryIO = try
482477
483478----------------------------------------------------------------
484479
485−plainHTTP :: TLSSettings -> Settings -> Socket -> S.ByteString -> IO (Connection, Transport)
486−plainHTTP TLSSettings{..} set s bs0 = case onInsecure of
480+plainHTTP :: TLSSettings -> Socket -> S.ByteString -> IO (Connection, Transport)
481+plainHTTP TLSSettings{..} s bs0 = case onInsecure of
487482 AllowInsecure -> do
488− conn' <- socketConnection set s
483+ conn' <- socketConnection s
489484 cachedRef <- I.newIORef bs0
490485 let conn'' = conn'
491486 { connRecv = recvPlain cachedRef (connRecv conn')
warp-tls/warp-tls.cabal+5−5
@@ -1,5 +1,5 @@
11Name: warp-tls
2−Version: 3.2.11
2+Version: 3.2.8
33Synopsis: HTTP over TLS support for Warp via the TLS package
44License: MIT
55License-file: LICENSE
@@ -18,16 +18,16 @@ description: SSLv1 and SSLv2 are obsoleted by IETF.
1818extra-source-files: ChangeLog.md README.md
1919
2020Library
21− Build-Depends: base >= 4.10 && < 5
21+ Build-Depends: base >= 4.8 && < 5
2222 , bytestring >= 0.9
2323 , wai >= 3.2 && < 3.3
24− , warp >= 3.3.6 && < 3.4
24+ , warp >= 3.2.17 && < 3.4
2525 , data-default-class >= 0.0.1
26− , tls >= 1.5.3
26+ , tls >= 1.3.10
2727 , cryptonite >= 0.12
2828 , network >= 2.2.1
2929 , streaming-commons
30− , tls-session-manager >= 0.0.4
30+ , tls-session-manager >= 0.0.0.1
3131 Exposed-modules: Network.Wai.Handler.WarpTLS
3232 ghc-options: -Wall
3333 if os(windows)
warp/ChangeLog.md+1−31
@@ -1,33 +1,3 @@
1−## 3.3.9
2−
3−* Don't insert Last-Modified: if exists.
4− [#791](https://github.com/yesodweb/wai/pull/791)
5−
6−## 3.3.8
7−
8−* Maximum header size is configurable.
9− [#781](https://github.com/yesodweb/wai/pull/781)
10−* Ignoring an exception from shutdown (gracefulClose).
11−
12−## 3.3.7
13−
14−* InvalidArgument (Bad file descriptor) is ignored in `receive`.
15− [#787](https://github.com/yesodweb/wai/pull/787)
16−
17−## 3.3.6
18−
19−* Fixing a bug of thread killed in the case of event source with
20− HTTP/2 (fixing #692 and #785)
21−* New APIs: clientCertificate to get client's certificate
22− [#783](https://github.com/yesodweb/wai/pull/783)
23−
24−## 3.3.5
25−
26−* New APIs: setGracefulCloseTimeout1 and setGracefulCloseTimeout2.
27− For HTTP/1.x, connections are closed immediately by default.
28− gracefullClose is used for HTTP/2 by default.
29− [#782](https://github.com/yesodweb/wai/pull/782)
30−
311## 3.3.4
322
333* Setting isSecure of HTTP/2 correctly.
@@ -50,7 +20,7 @@
5020## 3.3.0
5121
5222* Switching from the original implementation to HTTP/2 server library.
53− [#754](https://github.com/yesodweb/wai/pull/754)
23+ [#752](https://github.com/yesodweb/wai/pull/752)
5424* Breaking change: The type of `http2dataTrailers` is now
5525 `HTTP2Data -> TrailersMaker`.
5626
warp/Network/Wai/Handler/Warp.hs−50
@@ -72,9 +72,6 @@ module Network.Wai.Handler.Warp (
7272 , setLogger
7373 , setServerPushLogger
7474 , setGracefulShutdownTimeout
75− , setGracefulCloseTimeout1
76− , setGracefulCloseTimeout2
77− , setMaxTotalHeaderLength
7875 -- ** Getters
7976 , getPort
8077 , getHost
@@ -82,8 +79,6 @@ module Network.Wai.Handler.Warp (
8279 , getOnClose
8380 , getOnException
8481 , getGracefulShutdownTimeout
85− , getGracefulCloseTimeout1
86− , getGracefulCloseTimeout2
8782 -- ** Exception handler
8883 , defaultOnException
8984 , defaultShouldDisplayException
@@ -98,7 +93,6 @@ module Network.Wai.Handler.Warp (
9893 , pauseTimeout
9994 , FileInfo(..)
10095 , getFileInfo
101− , clientCertificate
10296 , withApplication
10397 , withApplicationSettings
10498 , testWithApplication
@@ -127,7 +121,6 @@ module Network.Wai.Handler.Warp (
127121import Control.Exception (SomeException, throwIO)
128122import Data.Streaming.Network (HostPreference)
129123import qualified Data.Vault.Lazy as Vault
130−import Data.X509
131124import qualified Network.HTTP.Types as H
132125import Network.Socket (SockAddr)
133126import Network.Wai (Request, Response, vault)
@@ -437,13 +430,6 @@ setGracefulShutdownTimeout :: Maybe Int
437430 -> Settings -> Settings
438431setGracefulShutdownTimeout time y = y { settingsGracefulShutdownTimeout = time }
439432
440−-- | Set the maximum header size that Warp will tolerate when using HTTP/1.x.
441−--
442−-- Since 3.3.8
443−setMaxTotalHeaderLength :: Int -> Settings -> Settings
444−setMaxTotalHeaderLength maxTotalHeaderLength settings = settings
445− { settingsMaxTotalHeaderLength = maxTotalHeaderLength }
446−
447433-- | Explicitly pause the slowloris timeout.
448434--
449435-- This is useful for cases where you partially consume a request body. For
@@ -471,39 +457,3 @@ pauseTimeout = fromMaybe (return ()) . Vault.lookup pauseTimeoutKey . vault
471457-- Since 3.1.10
472458getFileInfo :: Request -> FilePath -> IO FileInfo
473459getFileInfo = fromMaybe (\_ -> throwIO (userError "getFileInfo")) . Vault.lookup getFileInfoKey . vault
474−
475−-- | A timeout to limit the time (in milliseconds) waiting for
476−-- FIN for HTTP/1.x. 0 means uses immediate close.
477−-- Default: 0.
478−--
479−-- Since 3.3.5
480−setGracefulCloseTimeout1 :: Int -> Settings -> Settings
481−setGracefulCloseTimeout1 x y = y { settingsGracefulCloseTimeout1 = x }
482−
483−-- | A timeout to limit the time (in milliseconds) waiting for
484−-- FIN for HTTP/1.x. 0 means uses immediate close.
485−--
486−-- Since 3.3.5
487−getGracefulCloseTimeout1 :: Settings -> Int
488−getGracefulCloseTimeout1 = settingsGracefulCloseTimeout1
489−
490−-- | A timeout to limit the time (in milliseconds) waiting for
491−-- FIN for HTTP/2. 0 means uses immediate close.
492−-- Default: 2000.
493−--
494−-- Since 3.3.5
495−setGracefulCloseTimeout2 :: Int -> Settings -> Settings
496−setGracefulCloseTimeout2 x y = y { settingsGracefulCloseTimeout2 = x }
497−
498−-- | A timeout to limit the time (in milliseconds) waiting for
499−-- FIN for HTTP/2. 0 means uses immediate close.
500−--
501−-- Since 3.3.5
502−getGracefulCloseTimeout2 :: Settings -> Int
503−getGracefulCloseTimeout2 = settingsGracefulCloseTimeout2
504−
505−-- | Getting information of client certificate.
506−--
507−-- Since 3.3.5
508−clientCertificate :: Request -> Maybe CertificateChain
509−clientCertificate = join . Vault.lookup getClientCertificateKey . vault
warp/Network/Wai/Handler/Warp/File.hs+4−7
@@ -34,15 +34,12 @@ data RspFileInfo = WithoutBody H.Status
3434----------------------------------------------------------------
3535
3636conditionalRequest :: I.FileInfo
37− -> H.ResponseHeaders
38− -> IndexedHeader -- ^ Response
39− -> IndexedHeader -- ^ Request
37+ -> H.ResponseHeaders -> IndexedHeader
4038 -> RspFileInfo
41−conditionalRequest finfo hs0 rspidx reqidx = case condition of
39+conditionalRequest finfo hs0 reqidx = case condition of
4240 nobody@(WithoutBody _) -> nobody
43− WithBody s _ off len -> let !hs1 = addContentHeaders hs0 off len size
44− !hasLM = isJust $ rspidx ! fromEnum ResLastModified
45− !hs = [ (H.hLastModified,date) | not hasLM ] ++ hs1
41+ WithBody s _ off len -> let !hs = (H.hLastModified,date) :
42+ addContentHeaders hs0 off len size
4643 in WithBody s hs off len
4744 where
4845 !mtime = I.fileInfoTime finfo
warp/Network/Wai/Handler/Warp/HTTP2.hs+3−3
@@ -24,14 +24,14 @@ import Network.Wai.Handler.Warp.Types
2424
2525----------------------------------------------------------------
2626
27−http2 :: Connection -> Transport -> InternalInfo -> SockAddr -> S.Settings -> (BufSize -> IO ByteString) -> (ByteString -> IO ()) -> Application -> IO ()
28−http2 conn transport ii addr settings readN send app =
27+http2 :: Connection -> Transport -> InternalInfo -> SockAddr -> S.Settings -> (BufSize -> IO ByteString) -> Application -> IO ()
28+http2 conn transport ii addr settings readN app =
2929 H2.run conf http2server
3030 where
3131 conf = H2.Config {
3232 confWriteBuffer = connWriteBuffer conn
3333 , confBufferSize = connBufferSize conn
34− , confSendAll = send
34+ , confSendAll = connSendAll conn
3535 , confReadN = readN
3636 , confPositionReadMaker = pReadMaker ii
3737 }
warp/Network/Wai/Handler/Warp/HTTP2/Request.hs+1−2
@@ -22,7 +22,7 @@ import qualified System.TimeManager as T
2222
2323import Network.Wai.Handler.Warp.HTTP2.Types
2424import Network.Wai.Handler.Warp.Imports
25−import Network.Wai.Handler.Warp.Request (getFileInfoKey, pauseTimeoutKey, getClientCertificateKey)
25+import Network.Wai.Handler.Warp.Request (getFileInfoKey, pauseTimeoutKey)
2626import qualified Network.Wai.Handler.Warp.Settings as S (Settings, settingsNoParsePath)
2727import Network.Wai.Handler.Warp.Types
2828
@@ -83,7 +83,6 @@ toRequest' ii settings addr ref (reqths,reqvt) bodylen body th transport = retur
8383 $ Vault.insert setHTTP2DataKey (writeIORef ref)
8484 $ Vault.insert modifyHTTP2DataKey (modifyIORef' ref)
8585 $ Vault.insert pauseTimeoutKey (T.pause th)
86− $ Vault.insert getClientCertificateKey (tlsClientCertificate transport)
8786 Vault.empty
8887
8988getHTTP2DataKey :: Vault.Key (IO (Maybe HTTP2Data))
warp/Network/Wai/Handler/Warp/HTTP2/Response.hs+1−2
@@ -72,8 +72,7 @@ responseFile _ rsphdr isHead path Nothing ii reqhdr = do
7272 Left (_ex :: E.IOException) -> return $ response404 rsphdr
7373 Right finfo -> do
7474 let reqidx = indexRequestHeader reqhdr
75− rspidx = indexResponseHeader rsphdr
76− case conditionalRequest finfo rsphdr rspidx reqidx of
75+ case conditionalRequest finfo rsphdr reqidx of
7776 WithoutBody s -> return $ responseNoBody s rsphdr
7877 WithBody s rsphdr' off bytes -> do
7978 let !off' = fromIntegral off
warp/Network/Wai/Handler/Warp/Header.hs−2
@@ -69,7 +69,6 @@ indexResponseHeader hdr = traverseHeader hdr responseMaxIndex responseKeyIndex
6969data ResponseHeaderIndex = ResContentLength
7070 | ResServer
7171 | ResDate
72− | ResLastModified
7372 deriving (Enum,Bounded)
7473
7574-- | The size for 'IndexedHeader' for HTTP Response.
@@ -80,7 +79,6 @@ responseKeyIndex :: HeaderName -> Int
8079responseKeyIndex hn = case BS.length bs of
8180 4 -> if bs == "date" then fromEnum ResDate else -1
8281 6 -> if bs == "server" then fromEnum ResServer else -1
83− 13 -> if bs == "last-modified" then fromEnum ResLastModified else -1
8482 14 -> if bs == "content-length" then fromEnum ResContentLength else -1
8583 _ -> -1
8684 where
warp/Network/Wai/Handler/Warp/Recv.hs+1−13
@@ -17,9 +17,7 @@ import Foreign.C.Types
1717import Foreign.ForeignPtr (withForeignPtr)
1818import Foreign.Ptr (Ptr, castPtr, plusPtr)
1919import GHC.Conc (threadWaitRead)
20−import qualified GHC.IO.Exception as E
2120import Network.Socket (Socket)
22−import qualified System.IO.Error as E
2321#if MIN_VERSION_network(3,1,0)
2422import Network.Socket (withFdSocket)
2523#else
@@ -96,11 +94,8 @@ spell init0 siz0 recv recvBuf
9694 siz' = siz - len
9795 loop bss' siz'
9896
99−-- The timeout manager may close the socket.
100−-- In that case, an error of "Bad file descriptor" occurs.
101−-- We ignores it because we expect TimeoutThread.
10297receive :: Socket -> BufferPool -> Recv
103−receive sock pool = E.handle handler $ withBufferPool pool $ \ (ptr, size) -> do
98+receive sock pool = withBufferPool pool $ \ (ptr, size) -> do
10499#if MIN_VERSION_network(3,1,0)
105100 withFdSocket sock $ \fd -> do
106101#elif MIN_VERSION_network(3,0,0)
@@ -110,11 +105,6 @@ receive sock pool = E.handle handler $ withBufferPool pool $ \ (ptr, size) -> do
110105#endif
111106 let size' = fromIntegral size
112107 fromIntegral <$> receiveloop fd ptr size'
113− where
114− handler :: E.IOException -> IO ByteString
115− handler e
116− | E.ioeGetErrorType e == E.InvalidArgument = return ""
117− | otherwise = E.throwIO e
118108
119109receiveBuf :: Socket -> RecvBuf
120110receiveBuf sock buf0 siz0 = do
@@ -153,8 +143,6 @@ receiveloop sock ptr size = do
153143 else
154144 return bytes
155145
156−#ifndef mingw32_HOST_OS
157146-- fixme: the type of the return value
158147foreign import ccall unsafe "recv"
159148 c_recv :: CInt -> Ptr CChar -> CSize -> CInt -> IO CInt
160−#endif
warp/Network/Wai/Handler/Warp/Request.hs+17−18
@@ -9,7 +9,6 @@ module Network.Wai.Handler.Warp.Request (
99 , headerLines
1010 , pauseTimeoutKey
1111 , getFileInfoKey
12− , getClientCertificateKey
1312 , NoKeepAliveRequest (..)
1413 ) where
1514
@@ -22,7 +21,6 @@ import qualified Data.CaseInsensitive as CI
2221import qualified Data.IORef as I
2322import Data.Typeable (Typeable)
2423import qualified Data.Vault.Lazy as Vault
25−import Data.X509
2624import qualified Network.HTTP.Types as H
2725import Network.Socket (SockAddr)
2826import Network.Wai
@@ -38,7 +36,13 @@ import Network.Wai.Handler.Warp.Header
3836import Network.Wai.Handler.Warp.Imports hiding (readInt, lines)
3937import Network.Wai.Handler.Warp.ReadInt
4038import Network.Wai.Handler.Warp.RequestHeader
41−import Network.Wai.Handler.Warp.Settings (Settings, settingsNoParsePath, settingsMaxTotalHeaderLength)
39+import Network.Wai.Handler.Warp.Settings (Settings, settingsNoParsePath)
40+
41+----------------------------------------------------------------
42+
43+-- FIXME come up with good values here
44+maxTotalHeaderLength :: Int
45+maxTotalHeaderLength = 50 * 1024
4246
4347----------------------------------------------------------------
4448
@@ -62,7 +66,7 @@ recvRequest :: Bool -- ^ first request on this connection?
6266 -- Body producing action used for flushing the request body
6367
6468recvRequest firstRequest settings conn ii th addr src transport = do
65− hdrlines <- headerLines (settingsMaxTotalHeaderLength settings) firstRequest src
69+ hdrlines <- headerLines firstRequest src
6670 (method, unparsedPath, path, query, httpversion, hdr) <- parseHeaderLines hdrlines
6771 let idxhdr = indexRequestHeader hdr
6872 expect = idxhdr ! fromEnum ReqExpect
@@ -72,7 +76,6 @@ recvRequest firstRequest settings conn ii th addr src transport = do
7276 rawPath = if settingsNoParsePath settings then unparsedPath else path
7377 vaultValue = Vault.insert pauseTimeoutKey (Timeout.pause th)
7478 $ Vault.insert getFileInfoKey (getFileInfo ii)
75− $ Vault.insert getClientCertificateKey (tlsClientCertificate transport)
7679 Vault.empty
7780 (rbody, remainingRef, bodyLength) <- bodyAndSource src cl te
7881 -- body producing function which will produce '100-continue', if needed
@@ -101,8 +104,8 @@ recvRequest firstRequest settings conn ii th addr src transport = do
101104
102105----------------------------------------------------------------
103106
104−headerLines :: Int -> Bool -> Source -> IO [ByteString]
105−headerLines maxTotalHeaderLength firstRequest src = do
107+headerLines :: Bool -> Source -> IO [ByteString]
108+headerLines firstRequest src = do
106109 bs <- readSource src
107110 if S.null bs
108111 -- When we're working on a keep-alive connection and trying to
@@ -110,7 +113,7 @@ headerLines maxTotalHeaderLength firstRequest src = do
110113 -- lack of data as a real exception. See the http1 function in
111114 -- the Run module for more details.
112115 then if firstRequest then throwIO ConnectionClosedByPeer else throwIO NoKeepAliveRequest
113− else push maxTotalHeaderLength src (THStatus 0 id id) bs
116+ else push src (THStatus 0 id id) bs
114117
115118data NoKeepAliveRequest = NoKeepAliveRequest
116119 deriving (Show, Typeable)
@@ -220,8 +223,8 @@ close :: Sink ByteString IO a
220223close = throwIO IncompleteHeaders
221224-}
222225
223−push :: Int -> Source -> THStatus -> ByteString -> IO [ByteString]
224−push maxTotalHeaderLength src (THStatus len lines prepend) bs'
226+push :: Source -> THStatus -> ByteString -> IO [ByteString]
227+push src (THStatus len lines prepend) bs'
225228 -- Too many bytes
226229 | len > maxTotalHeaderLength = throwIO OverLargeHeader
227230 | otherwise = push' mnl
@@ -249,13 +252,13 @@ push maxTotalHeaderLength src (THStatus len lines prepend) bs'
249252 push' Nothing = do
250253 bst <- readSource' src
251254 when (S.null bst) $ throwIO IncompleteHeaders
252− push maxTotalHeaderLength src status bst
255+ push src status bst
253256 where
254257 len' = len + bsLen
255258 prepend' = S.append bs
256259 status = THStatus len' lines prepend'
257260 -- Found a newline, but next line continues as a multiline header
258− push' (Just (end, True)) = push maxTotalHeaderLength src status rest
261+ push' (Just (end, True)) = push src status rest
259262 where
260263 rest = S.drop (end + 1) bs
261264 prepend' = S.append (SU.unsafeTake (checkCR bs end) bs)
@@ -274,12 +277,12 @@ push maxTotalHeaderLength src (THStatus len lines prepend) bs'
274277 in if start < bsLen then
275278 -- more bytes in this chunk, push again
276279 let bs'' = SU.unsafeDrop start bs
277− in push maxTotalHeaderLength src status bs''
280+ in push src status bs''
278281 else do
279282 -- no more bytes in this chunk, ask for more
280283 bst <- readSource' src
281284 when (S.null bs) $ throwIO IncompleteHeaders
282− push maxTotalHeaderLength src status bst
285+ push src status bst
283286 where
284287 start = end + 1 -- start of next chunk
285288 line = SU.unsafeTake (checkCR bs end) bs
@@ -297,7 +300,3 @@ pauseTimeoutKey = unsafePerformIO Vault.newKey
297300getFileInfoKey :: Vault.Key (FilePath -> IO FileInfo)
298301getFileInfoKey = unsafePerformIO Vault.newKey
299302{-# NOINLINE getFileInfoKey #-}
300−
301−getClientCertificateKey :: Vault.Key (Maybe CertificateChain)
302−getClientCertificateKey = unsafePerformIO Vault.newKey
303−{-# NOINLINE getClientCertificateKey #-}
warp/Network/Wai/Handler/Warp/Response.hs+16−19
@@ -116,14 +116,14 @@ sendResponse settings conn ii th req reqidxhdr src response = do
116116 -- and status, the response to HEAD is processed here.
117117 --
118118 -- See definition of rsp below for proper body stripping.
119− (ms, mlen) <- sendRsp conn ii ver s hs rspidxhdr rsp
119+ (ms, mlen) <- sendRsp conn ii ver s hs rsp
120120 case ms of
121121 Nothing -> return ()
122122 Just realStatus -> logger req realStatus mlen
123123 T.tickle th
124124 return ret
125125 else do
126− _ <- sendRsp conn ii ver s hs rspidxhdr RspNoBody
126+ _ <- sendRsp conn ii ver s hs RspNoBody
127127 logger req s Nothing
128128 T.tickle th
129129 return isPersist
@@ -196,13 +196,12 @@ sendRsp :: Connection
196196 -> H.HttpVersion
197197 -> H.Status
198198 -> H.ResponseHeaders
199− -> IndexedHeader -- Response
200199 -> Rsp
201200 -> IO (Maybe H.Status, Maybe Integer)
202201
203202----------------------------------------------------------------
204203
205−sendRsp conn _ ver s hs _ RspNoBody = do
204+sendRsp conn _ ver s hs RspNoBody = do
206205 -- Not adding Content-Length.
207206 -- User agents treats it as Content-Length: 0.
208207 composeHeader ver s hs >>= connSendAll conn
@@ -210,7 +209,7 @@ sendRsp conn _ ver s hs _ RspNoBody = do
210209
211210----------------------------------------------------------------
212211
213−sendRsp conn _ ver s hs _ (RspBuilder body needsChunked) = do
212+sendRsp conn _ ver s hs (RspBuilder body needsChunked) = do
214213 header <- composeHeaderBuilder ver s hs needsChunked
215214 let hdrBdy
216215 | needsChunked = header <> chunkedTransferEncoding body
@@ -223,7 +222,7 @@ sendRsp conn _ ver s hs _ (RspBuilder body needsChunked) = do
223222
224223----------------------------------------------------------------
225224
226−sendRsp conn _ ver s hs _ (RspStream streamingBody needsChunked th) = do
225+sendRsp conn _ ver s hs (RspStream streamingBody needsChunked th) = do
227226 header <- composeHeaderBuilder ver s hs needsChunked
228227 (recv, finish) <- newByteStringBuilderRecv $ reuseBufferStrategy
229228 $ toBuilderBuffer (connWriteBuffer conn) (connBufferSize conn)
@@ -247,7 +246,7 @@ sendRsp conn _ ver s hs _ (RspStream streamingBody needsChunked th) = do
247246
248247----------------------------------------------------------------
249248
250−sendRsp conn _ _ _ _ _ (RspRaw withApp src tickle) = do
249+sendRsp conn _ _ _ _ (RspRaw withApp src tickle) = do
251250 withApp recv send
252251 return (Nothing, Nothing)
253252 where
@@ -261,8 +260,8 @@ sendRsp conn _ _ _ _ _ (RspRaw withApp src tickle) = do
261260
262261-- Sophisticated WAI applications.
263262-- We respect s0. s0 MUST be a proper value.
264−sendRsp conn ii ver s0 hs0 rspidxhdr (RspFile path (Just part) _ isHead hook) =
265− sendRspFile2XX conn ii ver s0 hs rspidxhdr path beg len isHead hook
263+sendRsp conn ii ver s0 hs0 (RspFile path (Just part) _ isHead hook) =
264+ sendRspFile2XX conn ii ver s0 hs path beg len isHead hook
266265 where
267266 beg = filePartOffset part
268267 len = filePartByteCount part
@@ -272,17 +271,17 @@ sendRsp conn ii ver s0 hs0 rspidxhdr (RspFile path (Just part) _ isHead hook) =
272271
273272-- Simple WAI applications.
274273-- Status is ignored
275−sendRsp conn ii ver _ hs0 rspidxhdr (RspFile path Nothing reqidxhdr isHead hook) = do
274+sendRsp conn ii ver _ hs0 (RspFile path Nothing idxhdr isHead hook) = do
276275 efinfo <- E.try $ getFileInfo ii path
277276 case efinfo of
278277 Left (_ex :: E.IOException) ->
279278#ifdef WARP_DEBUG
280279 print _ex >>
281280#endif
282− sendRspFile404 conn ii ver hs0 rspidxhdr
283− Right finfo -> case conditionalRequest finfo hs0 rspidxhdr reqidxhdr of
284− WithoutBody s -> sendRsp conn ii ver s hs0 rspidxhdr RspNoBody
285− WithBody s hs beg len -> sendRspFile2XX conn ii ver s hs rspidxhdr path beg len isHead hook
281+ sendRspFile404 conn ii ver hs0
282+ Right finfo -> case conditionalRequest finfo hs0 idxhdr of
283+ WithoutBody s -> sendRsp conn ii ver s hs0 RspNoBody
284+ WithBody s hs beg len -> sendRspFile2XX conn ii ver s hs path beg len isHead hook
286285
287286----------------------------------------------------------------
288287
@@ -291,15 +290,14 @@ sendRspFile2XX :: Connection
291290 -> H.HttpVersion
292291 -> H.Status
293292 -> H.ResponseHeaders
294− -> IndexedHeader
295293 -> FilePath
296294 -> Integer
297295 -> Integer
298296 -> Bool
299297 -> IO ()
300298 -> IO (Maybe H.Status, Maybe Integer)
301−sendRspFile2XX conn ii ver s hs rspidxhdr path beg len isHead hook
302− | isHead = sendRsp conn ii ver s hs rspidxhdr RspNoBody
299+sendRspFile2XX conn ii ver s hs path beg len isHead hook
300+ | isHead = sendRsp conn ii ver s hs RspNoBody
303301 | otherwise = do
304302 lheader <- composeHeader ver s hs
305303 (mfd, fresher) <- getFd ii path
@@ -312,9 +310,8 @@ sendRspFile404 :: Connection
312310 -> InternalInfo
313311 -> H.HttpVersion
314312 -> H.ResponseHeaders
315− -> IndexedHeader
316313 -> IO (Maybe H.Status, Maybe Integer)
317−sendRspFile404 conn ii ver hs0 rspidxhdr = sendRsp conn ii ver s hs rspidxhdr (RspBuilder body True)
314+sendRspFile404 conn ii ver hs0 = sendRsp conn ii ver s hs (RspBuilder body True)
318315 where
319316 s = H.notFound404
320317 hs = replaceHeader H.hContentType "text/plain; charset=utf-8" hs0
warp/Network/Wai/Handler/Warp/Run.hs+24−34
@@ -17,7 +17,7 @@ import qualified Control.Concurrent as Conc (yield)
1717import Control.Exception as E
1818import qualified Data.ByteString as S
1919import Data.Char (chr)
20−import Data.IORef (IORef, newIORef, readIORef, writeIORef)
20+import Data.IORef (IORef, newIORef, readIORef, writeIORef, atomicModifyIORef')
2121import Data.Streaming.Network (bindPortTCP)
2222import Foreign.C.Error (Errno(..), eCONNABORTED)
2323import GHC.IO.Exception (IOException(..))
@@ -58,29 +58,17 @@ import Network.Socket (fdSocket)
5858#endif
5959
6060-- | Creating 'Connection' for plain HTTP based on a given socket.
61−socketConnection :: Settings -> Socket -> IO Connection
62−#if MIN_VERSION_network(3,1,1)
63−socketConnection set s = do
64−#else
65−socketConnection _ s = do
66−#endif
61+socketConnection :: Socket -> IO Connection
62+socketConnection s = do
6763 bufferPool <- newBufferPool
6864 writeBuf <- allocateBuffer bufferSize
6965 let sendall = Sock.sendAll s
70− isH2 <- newIORef False -- HTTP/1.x
7166 return Connection {
7267 connSendMany = Sock.sendMany s
7368 , connSendAll = sendall
7469 , connSendFile = sendFile s writeBuf bufferSize sendall
7570#if MIN_VERSION_network(3,1,1)
76− , connClose = do
77− h2 <- readIORef isH2
78− let tm = if h2 then settingsGracefulCloseTimeout2 set
79− else settingsGracefulCloseTimeout1 set
80− if tm == 0 then
81− close s
82− else
83− gracefulClose s tm `E.catch` \(E.SomeException _) -> return ()
71+ , connClose = gracefulClose s 5000
8472#else
8573 , connClose = close s
8674#endif
@@ -89,7 +77,6 @@ socketConnection _ s = do
8977 , connRecvBuf = receiveBuf s
9078 , connWriteBuffer = writeBuf
9179 , connBufferSize = bufferSize
92− , connHTTP2 = isH2
9380 }
9481
9582-- | Run an 'Application' on the given port.
@@ -151,7 +138,7 @@ runSettingsSocket set socket app = do
151138 setSocketCloseOnExec s
152139 -- NoDelay causes an error for AF_UNIX.
153140 setSocketOption s NoDelay 1 `E.catch` \(E.SomeException _) -> return ()
154− conn <- socketConnection set s
141+ conn <- socketConnection s
155142 return (conn, sa)
156143
157144 closeListenSocket = close socket
@@ -286,7 +273,10 @@ fork :: Settings
286273fork set mkConn addr app counter ii = settingsFork set $ \unmask ->
287274 -- Call the user-supplied on exception code if any
288275 -- exceptions are thrown.
289− handle (settingsOnException set Nothing) $
276+ handle (settingsOnException set Nothing) .
277+ -- Allocate a new IORef indicating whether the connection has been
278+ -- closed, to avoid double-freeing a connection
279+ withClosedRef $ \ref ->
290280 -- Run the connection maker to get a new connection, and ensure
291281 -- that the connection is closed. If the mkConn call throws an
292282 -- exception, we will leak the connection. If the mkConn call is
@@ -297,13 +287,21 @@ fork set mkConn addr app counter ii = settingsFork set $ \unmask ->
297287 -- We grab the connection before registering timeouts since the
298288 -- timeouts will be useless during connection creation, due to the
299289 -- fact that async exceptions are still masked.
300− bracket mkConn cleanUp (serve unmask)
290+ bracket mkConn (cleanUp ref) (serve unmask ref)
301291 where
302− cleanUp (conn, _) = connClose conn `finally` connFree conn
292+ withClosedRef inner = newIORef False >>= inner
293+
294+ closeConn ref conn = do
295+ isClosed <- atomicModifyIORef' ref $ \x -> (True, x)
296+ unless isClosed $ connClose conn
297+
298+ cleanUp ref (conn, _) = closeConn ref conn `finally` connFree conn
303299
304300 -- We need to register a timeout handler for this thread, and
305− -- cancel that handler as soon as we exit.
306− serve unmask (conn, transport) = bracket register cancel $ \th -> do
301+ -- cancel that handler as soon as we exit. We additionally close
302+ -- the connection immediately in case the child thread catches the
303+ -- async exception or performs some long-running cleanup action.
304+ serve unmask ref (conn, transport) = bracket register cancel $ \th -> do
307305 -- We now have fully registered a connection close handler in
308306 -- the case of all exceptions, so it is safe to once again
309307 -- allow async exceptions.
@@ -315,7 +313,8 @@ fork set mkConn addr app counter ii = settingsFork set $ \unmask ->
315313 -- above ensures the connection is closed.
316314 when goingon $ serveConnection conn ii th addr transport set app
317315 where
318− register = T.registerKillThread (timeoutManager ii) (connClose conn)
316+ register = T.registerKillThread (timeoutManager ii)
317+ (closeConn ref conn)
319318 cancel = T.cancel
320319
321320 onOpen adr = increase counter >> settingsOnOpen set adr
@@ -342,19 +341,10 @@ serveConnection conn ii th origAddr transport settings app = do
342341 istatus <- newIORef False
343342 if settingsHTTP2Enabled settings && h2 then do
344343 rawRecvN <- makeReceiveN bs (connRecv conn) (connRecvBuf conn)
345− -- This thread becomes the sender in http2 library.
346− -- In the case of event source, one request comes and one
347− -- worker gets busy. But it is likely that the receiver does
348− -- not receive any data at all while the sender is sending
349− -- output data from the worker. It's not good enough to tickle
350− -- the time handler in the receiver only. So, we should tickle
351− -- the time handler in both the receiver and the sender.
352344 let recvN = wrappedRecvN th istatus (settingsSlowlorisSize settings) rawRecvN
353− sendBS x = connSendAll conn x >> T.tickle th
354345 -- fixme: origAddr
355346 checkTLS
356− setConnHTTP2 conn True
357− http2 conn transport ii origAddr settings recvN sendBS app
347+ http2 conn transport ii origAddr settings recvN app
358348 else do
359349 src <- mkSource (wrappedRecv conn th istatus (settingsSlowlorisSize settings))
360350 writeIORef istatus True
warp/Network/Wai/Handler/Warp/Settings.hs+5−31
@@ -76,13 +76,6 @@ data Settings = Settings
7676 --
7777 -- Since 2.0.3
7878 , settingsInstallShutdownHandler :: IO () -> IO ()
79− -- ^ An action to install a handler (e.g. Unix signal handler)
80− -- to close a listen socket.
81− -- The first argument is an action to close the listen socket.
82− --
83− -- Default: no action
84− --
85− -- Since 3.0.1
8679 , settingsServerName :: ByteString
8780 -- ^ Default server name if application does not set one.
8881 --
@@ -94,44 +87,28 @@ data Settings = Settings
9487 , settingsProxyProtocol :: ProxyProtocol
9588 -- ^ Specify usage of the PROXY protocol.
9689 --
97− -- Since 3.0.5
90+ -- Since 3.0.5.
9891 , settingsSlowlorisSize :: Int
9992 -- ^ Size of bytes read to prevent Slowloris protection. Default value: 2048
10093 --
101− -- Since 3.1.2
94+ -- Since 3.1.2.
10295 , settingsHTTP2Enabled :: Bool
10396 -- ^ Whether to enable HTTP2 ALPN/upgrades. Default: True
10497 --
105− -- Since 3.1.7
98+ -- Since 3.1.7.
10699 , settingsLogger :: Request -> H.Status -> Maybe Integer -> IO ()
107100 -- ^ A log function. Default: no action.
108101 --
109− -- Since 3.1.10
102+ -- Since 3.X.X.
110103 , settingsServerPushLogger :: Request -> ByteString -> Integer -> IO ()
111104 -- ^ A HTTP/2 server push log function. Default: no action.
112105 --
113− -- Since 3.2.7
106+ -- Since 3.X.X.
114107 , settingsGracefulShutdownTimeout :: Maybe Int
115108 -- ^ An optional timeout to limit the time (in seconds) waiting for
116109 -- a graceful shutdown of the web server.
117110 --
118111 -- Since 3.2.8
119− , settingsGracefulCloseTimeout1 :: Int
120− -- ^ A timeout to limit the time (in milliseconds) waiting for
121− -- FIN for HTTP/1.x. 0 means uses immediate close.
122− -- Default: 0.
123− --
124− -- Since 3.3.5
125− , settingsGracefulCloseTimeout2 :: Int
126− -- ^ A timeout to limit the time (in milliseconds) waiting for
127− -- FIN for HTTP/2. 0 means uses immediate close.
128− -- Default: 2000.
129− --
130− -- Since 3.3.5
131− , settingsMaxTotalHeaderLength :: Int
132− -- ^ Determines the maximum header size that Warp will tolerate when using HTTP/1.x.
133− --
134− -- Since 3.3.8
135112 }
136113
137114-- | Specify usage of the PROXY protocol.
@@ -168,9 +145,6 @@ defaultSettings = Settings
168145 , settingsLogger = \_ _ _ -> return ()
169146 , settingsServerPushLogger = \_ _ _ -> return ()
170147 , settingsGracefulShutdownTimeout = Nothing
171− , settingsGracefulCloseTimeout1 = 0
172− , settingsGracefulCloseTimeout2 = 2000
173− , settingsMaxTotalHeaderLength = 50 * 1024
174148 }
175149
176150-- | Apply the logic provided by 'defaultOnException' to determine if an
warp/Network/Wai/Handler/Warp/Types.hs−10
@@ -8,7 +8,6 @@ import Control.Exception
88import qualified Data.ByteString as S
99import Data.IORef (IORef, readIORef, writeIORef, newIORef)
1010import Data.Typeable (Typeable)
11−import Data.X509
1211import Foreign.Ptr (Ptr)
1312import System.Posix.Types (Fd)
1413import qualified System.TimeManager as T
@@ -123,16 +122,8 @@ data Connection = Connection {
123122 , connWriteBuffer :: Buffer
124123 -- | The size of the write buffer.
125124 , connBufferSize :: BufSize
126− -- | Is this connection HTTP/2?
127− , connHTTP2 :: IORef Bool
128125 }
129126
130−getConnHTTP2 :: Connection -> IO Bool
131−getConnHTTP2 conn = readIORef (connHTTP2 conn)
132−
133−setConnHTTP2 :: Connection -> Bool -> IO ()
134−setConnHTTP2 conn b = writeIORef (connHTTP2 conn) b
135−
136127----------------------------------------------------------------
137128
138129data InternalInfo = InternalInfo {
@@ -180,7 +171,6 @@ data Transport = TCP -- ^ Plain channel: TCP
180171 , tlsMinorVersion :: Int
181172 , tlsNegotiatedProtocol :: Maybe ByteString -- ^ The result of Application Layer Protocol Negociation in RFC 7301
182173 , tlsChiperID :: Word16
183− , tlsClientCertificate :: Maybe CertificateChain
184174 } -- ^ Encrypted channel: TLS or SSL
185175
186176isTransportSecure :: Transport -> Bool
warp/test/FileSpec.hs+1−1
@@ -21,7 +21,7 @@ testFileRange desc reqhs file ans = it desc $ do
2121 let WithBody s hs off len = ans
2222 hs' = ("Last-Modified",fileInfoDate finfo) : hs
2323 ans' = WithBody s hs' off len
24− conditionalRequest finfo [] (indexResponseHeader hs) (indexRequestHeader reqhs) `shouldBe` ans'
24+ conditionalRequest finfo [] (indexRequestHeader reqhs) `shouldBe` ans'
2525
2626spec :: Spec
2727spec = do
warp/test/RequestSpec.hs+7−11
@@ -7,7 +7,6 @@ module RequestSpec (main, spec) where
77import Network.Wai.Handler.Warp.File (parseByteRanges)
88import Network.Wai.Handler.Warp.Request
99import Network.Wai.Handler.Warp.Types
10−import Network.Wai.Handler.Warp.Settings (settingsMaxTotalHeaderLength, defaultSettings)
1110import Test.Hspec
1211import Test.Hspec.QuickCheck
1312import qualified Data.ByteString as S
@@ -18,9 +17,6 @@ import Data.IORef
1817main :: IO ()
1918main = hspec spec
2019
21−defaultMaxTotalHeaderLength :: Int
22−defaultMaxTotalHeaderLength = settingsMaxTotalHeaderLength defaultSettings
23−
2420spec :: Spec
2521spec = do
2622 describe "headerLines" $ do
@@ -67,29 +63,29 @@ spec = do
6763 describe "headerLines" $ do
6864 it "can handle a nomarl case" $ do
6965 src <- mkSourceFunc ["Status: 200\r\nContent-Type: text/plain\r\n\r\n"] >>= mkSource
70− x <- headerLines defaultMaxTotalHeaderLength True src
66+ x <- headerLines True src
7167 x `shouldBe` ["Status: 200", "Content-Type: text/plain"]
7268
7369 it "can handle a nasty case (1)" $ do
7470 src <- mkSourceFunc ["Status: 200", "\r\nContent-Type: text/plain", "\r\n\r\n"] >>= mkSource
75− x <- headerLines defaultMaxTotalHeaderLength True src
71+ x <- headerLines True src
7672 x `shouldBe` ["Status: 200", "Content-Type: text/plain"]
7773
7874 it "can handle a nasty case (1)" $ do
7975 src <- mkSourceFunc ["Status: 200", "\r", "\nContent-Type: text/plain", "\r", "\n\r\n"] >>= mkSource
80− x <- headerLines defaultMaxTotalHeaderLength True src
76+ x <- headerLines True src
8177 x `shouldBe` ["Status: 200", "Content-Type: text/plain"]
8278
8379 it "can handle a nasty case (1)" $ do
8480 src <- mkSourceFunc ["Status: 200", "\r", "\n", "Content-Type: text/plain", "\r", "\n", "\r", "\n"] >>= mkSource
85− x <- headerLines defaultMaxTotalHeaderLength True src
81+ x <- headerLines True src
8682 x `shouldBe` ["Status: 200", "Content-Type: text/plain"]
8783
8884 it "can handle an illegal case (1)" $ do
8985 src <- mkSourceFunc ["\nStatus:", "\n 200", "\nContent-Type: text/plain", "\r\n\r\n"] >>= mkSource
90− x <- headerLines defaultMaxTotalHeaderLength True src
86+ x <- headerLines True src
9187 x `shouldBe` []
92− y <- headerLines defaultMaxTotalHeaderLength True src
88+ y <- headerLines True src
9389 y `shouldBe` ["Status: 200", "Content-Type: text/plain"]
9490
9591 where
@@ -115,7 +111,7 @@ headerLinesList' orig = do
115111 writeIORef ref z
116112 return y
117113 src' <- mkSource src
118− res <- headerLines defaultMaxTotalHeaderLength True src'
114+ res <- headerLines True src'
119115 return (res, src')
120116
121117consumeLen :: Int -> Source -> IO S8.ByteString
warp/warp.cabal+1−4
@@ -1,5 +1,5 @@
11Name: warp
2−Version: 3.3.9
2+Version: 3.3.4
33Synopsis: A fast, light-weight web server for WAI applications.
44License: MIT
55License-file: LICENSE
@@ -56,7 +56,6 @@ Library
5656 , vault >= 0.3
5757 , wai >= 3.2 && < 3.3
5858 , word8
59− , x509
6059 if impl(ghc < 8)
6160 Build-Depends: semigroups
6261 if flag(network-bytestring)
@@ -212,7 +211,6 @@ Test-Suite spec
212211 , vault
213212 , wai >= 3.2 && < 3.3
214213 , word8
215− , x509
216214 -- Build-Tool-Depends: hspec-discover:hspec-discover
217215 if impl(ghc < 8)
218216 Build-Depends: semigroups
@@ -251,7 +249,6 @@ Benchmark parser
251249 , network
252250 , time-manager
253251 , unix-compat
254− , x509
255252 if impl(ghc < 8)
256253 Build-Depends: semigroups
257254