servant-snap-0.8.4: test/Servant/Server/CORSSpec.hs
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
module Servant.Server.CORSSpec where
import Control.Monad.IO.Class (liftIO)
import Data.List (foldl')
import Data.Proxy
import Servant.API ((:<|>) (..), (:>), BasicAuth,
Capture, CaptureAll, Header (..),
Headers, IsSecure (..), JSON,
NoContent (..), NoFraming,
OctetStream, PlainText, QueryFlag,
QueryParam, QueryParams, Raw,
RemoteHost, ReqBody, SourceIO,
Stream, addHeader)
import Servant.API.Verbs (Delete, Get, Patch, Post, Put,
Verb)
import Servant.Server hiding (route)
import Servant.Server.Internal (HasServer)
import Snap
import qualified Snap.Core as SC
import qualified Snap.Test as ST
import qualified Snap.Util.CORS as CORS
import Test.Hspec
import Servant.Utils.SnapTestUtils
-- TODO: Cleanup
spec :: Spec
spec = do
corsSanitySpec
corsSanitySpec :: Spec
corsSanitySpec = do
let handler = CORS.applyCORS CORS.defaultOptions bareEndpoint
bareEndpoint = return ()
servantEndpoint :: Snap ()
servantEndpoint = do
let printHeaders m r = liftIO $ putStrLn m >> print (headers r)
respA <- SC.getResponse
serveSnap (Proxy :: Proxy ("int" :> Get '[JSON] Int)) (return 5 :: Snap Int)
servantSnapletInit :: SnapletInit () ()
servantSnapletInit = makeSnaplet "servant-test" "Testing servant" Nothing $ do
addRoutes [
("other", SC.writeText "other route")
,("", servantSnapletHandler)
]
wrapSite (CORS.applyCORS CORS.defaultOptions)
return ()
servantSnapletHandler :: Handler () () ()
servantSnapletHandler = do
let printHeaders m r = liftIO $ putStrLn m >> print (headers r)
respA <- SC.getResponse
serveSnap (Proxy :: Proxy ("int" :> Get '[JSON] Int)) (return 5 :: Handler () () Int)
forwardHeaders :: Snap ()
forwardHeaders = do
req <- SC.getRequest
resp <- SC.getResponse
putResponse $ foldl' (\r (hk, hv) -> SC.setHeader hk hv r) resp (listHeaders req)
req :: ST.RequestBuilder IO ()
req = do
ST.setRequestType $ ST.RequestWithRawBody GET ""
ST.setRequestPath "/"
ST.setHeader "Origin" "http://origin.org"
req' :: ST.RequestBuilder IO ()
req' = do
ST.setRequestType $ ST.RequestWithRawBody GET ""
ST.setRequestPath "int"
ST.setHeader "Origin" "http://origin.org"
req'' :: ST.RequestBuilder IO ()
req'' = do
ST.setRequestType $ ST.RequestWithRawBody GET ""
ST.setRequestPath "other"
ST.setHeader "Origin" "http://origin.org"
it "Sets CORS and forwards req headers for Snap non-servant handler" $ do
resp <- ST.runHandler req (forwardHeaders >> handler)
Right resp `shouldHaveStatus` 200
Right resp `shouldHaveHeaders` [("Origin", "http://origin.org")
,("Access-Control-Allow-Origin", "http://origin.org")]
it "Sets CORS and forwards req headers for Snap handler" $ do
resp <- ST.runHandler req' (CORS.applyCORS CORS.defaultOptions $ forwardHeaders >> servantEndpoint)
Right resp `shouldHaveStatus` 200
Right resp `shouldDecodeTo` (5 :: Int)
Right resp `shouldHaveHeaders` [("Origin", "http://origin.org")
,("Access-Control-Allow-Origin", "http://origin.org")
]
it "Sets CORS and forwards req headers for Snaplet servant handler with wrapSite" $ do
resp <- testSnaplet servantSnapletInit req'
resp `shouldHaveStatus` 200
resp `shouldDecodeTo` (5 :: Int)
resp `shouldHaveHeaders` [("Access-Control-Allow-Origin", "http://origin.org")
]
it "Sets CORS and forwards req headers for Snaplet not-servant handler with wrapSite" $ do
resp <- testSnaplet servantSnapletInit req''
resp `shouldHaveStatus` 200
resp `shouldHaveHeaders` [("Access-Control-Allow-Origin", "http://origin.org")
]