@@ -0,0 +1,56 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Network.Wai.Middleware.ForceSSLSpec
3+ ( main
4+ , spec
5+ ) where
6+
7+import Test.Hspec
8+
9+import Network.Wai.Middleware.ForceSSL
10+
11+import Data.ByteString (ByteString)
12+import Data.Monoid ((<>))
13+import Network.HTTP.Types (methodPost, status200, status301, status307)
14+import Network.Wai
15+import Network.Wai.Test
16+
17+main :: IO ()
18+main = hspec spec
19+
20+spec :: Spec
21+spec = describe "forceSSL" $ do
22+ let host = "example.com"
23+
24+ it "redirects non-https requests to https" $ do
25+ resp <- runApp host forceSSL defaultRequest
26+
27+ simpleStatus resp `shouldBe` status301
28+ simpleHeaders resp `shouldBe` [("Location", "https://" <> host)]
29+
30+ it "redirects with 307 in the case of a non-GET request" $ do
31+ resp <- runApp host forceSSL defaultRequest
32+ { requestMethod = methodPost }
33+
34+ simpleStatus resp `shouldBe` status307
35+ simpleHeaders resp `shouldBe` [("Location", "https://" <> host)]
36+
37+ it "does not redirect already-secure requests" $ do
38+ resp <- runApp host forceSSL defaultRequest { isSecure = True }
39+
40+ simpleStatus resp `shouldBe` status200
41+
42+ it "preserves the original path and query string" $ do
43+ resp <- runApp host forceSSL defaultRequest
44+ { rawPathInfo = "/foo/bar"
45+ , rawQueryString = "?baz=bat"
46+ }
47+
48+ simpleHeaders resp `shouldBe`
49+ [("Location", "https://" <> host <> "/foo/bar?baz=bat")]
50+
51+runApp :: ByteString -> Middleware -> Request -> IO SResponse
52+runApp host mw req = runSession
53+ (request req { requestHeaderHost = Just $ host <> ":80" }) $ mw app
54+
55+ where
56+ app _ respond = respond $ responseLBS status200 [] ""