on master help sign in
add routed middleware function
commit698d4663bd9cf03971086bb0a6ec791ab4f3769c authorGreg Weber <greg@gregweber.info> dateSat 13 Jun 2015, 08:57 (11 years ago) parent52f892c
3 files changed+85
wai-extra/Network/Wai/Middleware/Routed.hs+30 wai-extra/test/Network/Wai/Middleware/RoutedSpec.hs+53 wai-extra/wai-extra.cabal+2
wai-extra/Network/Wai/Middleware/Routed.hsnew file+30
@@ -0,0 +1,30 @@
1+module Network.Wai.Middleware.Routed where
2+
3+import Network.Wai
4+import Data.ByteString (ByteString)
5+import Data.Text (Text)
6+
7+-- | Apply a middleware based on a test of pathInfo
8+--
9+-- example:
10+--
11+-- > let corsify = routedMiddleWare ("static" `elem`) addCorsHeaders
12+--
13+routedMiddleware :: ([Text] -> Bool) -- ^ Only use middleware if this pathInfo test returns True
14+ -> Middleware -- ^ middleware to apply the path prefix guard to
15+ -> Middleware -- ^ modified middleware
16+routedMiddleware pathCheck middle app req
17+ | pathCheck (pathInfo req) = middle app req
18+ | otherwise = app req
19+
20+-- | Only apply the middleware to certain hosts
21+hostedMiddleware :: ByteString -- ^ Domain the middleware applies to
22+ -> Middleware -- ^ middleware to apply the path prefix guard to
23+ -> Middleware -- ^ modified middleware
24+hostedMiddleware domain middle app req
25+ | hasDomain domain req = middle app req
26+ | otherwise = app req
27+
28+hasDomain :: ByteString -> Request -> Bool
29+hasDomain domain req = maybe False (== domain) mHost
30+ where mHost = requestHeaderHost req
wai-extra/test/Network/Wai/Middleware/RoutedSpec.hsnew file+53
@@ -0,0 +1,53 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+module Network.Wai.Middleware.RoutedSpec
3+ ( main
4+ , spec
5+ ) where
6+
7+import Test.Hspec
8+
9+import Network.Wai.Middleware.Routed
10+import Network.Wai.Middleware.ForceSSL (forceSSL)
11+
12+import Network.HTTP.Types (methodPost, status200, status301, status307)
13+import Network.Wai
14+import Network.Wai.Test
15+import Data.ByteString (ByteString)
16+import Data.String (IsString)
17+
18+main :: IO ()
19+main = hspec spec
20+
21+spec :: Spec
22+spec = describe "forceSSL" $ do
23+ it "routed middleware" $ do
24+ let destination = "https://example.com/d/"
25+ let routedSslJsonApp prefix = routedMiddleware (checkPrefix prefix) forceSSL jsonApp
26+ checkPrefix p (p1:_) = p == p1
27+ checkPrefix _ _ = False
28+
29+ flip runSession (routedSslJsonApp "r") $ do
30+ res <- testDPath "http"
31+ assertNoHeader location res
32+ assertStatus 200 res
33+ assertBody "{\"foo\":\"bar\"}" res
34+
35+ flip runSession (routedSslJsonApp "d") $ do
36+ res2 <- testDPath "http"
37+ assertHeader location destination res2
38+ assertStatus 301 res2
39+
40+jsonApp :: Application
41+jsonApp _req cps = cps $ responseLBS status200
42+ [("Content-Type", "application/json")]
43+ "{\"foo\":\"bar\"}"
44+
45+testDPath :: ByteString -> Session SResponse
46+testDPath proto =
47+ request $ flip setRawPathInfo "/d/" defaultRequest
48+ { requestHeaders = [("X-Forwarded-Proto", proto)]
49+ , requestHeaderHost = Just "example.com"
50+ }
51+
52+location :: IsString ci => ci
53+location = "Location"
wai-extra/wai-extra.cabal+2
@@ -135,6 +135,7 @@ Library
135135 Network.Wai.Middleware.HttpAuth
136136 Network.Wai.Middleware.StreamFile
137137 Network.Wai.Middleware.ForceSSL
138+ Network.Wai.Middleware.Routed
138139 Network.Wai.Parse
139140 Network.Wai.Request
140141 Network.Wai.UrlMap
@@ -153,6 +154,7 @@ test-suite spec
153154 Network.Wai.RequestSpec
154155 Network.Wai.Middleware.ApprootSpec
155156 Network.Wai.Middleware.ForceSSLSpec
157+ Network.Wai.Middleware.RoutedSpec
156158 Network.Wai.Middleware.StripHeadersSpec
157159 WaiExtraSpec
158160 build-depends: base >= 4 && < 5