graphql-engine/server/src-lib/Hasura/Server/Middleware.hs
Brandon Simmons ff62d5e0bf Migrate to GHC 8.10, upgrade dependencies. Closes #4517
This also seems to squash a stubborn space leak we see with
subscriptions (linking to canonical #3388 for reference).

This may also fix some of the "Unexpected exception" websockets
exceptions we are now surfacing (see e.g. #4344)

Also: dev.sh: fix hpc reporting

Initial work on this done by Vamshi.
2020-05-13 19:13:02 -04:00

68 lines
2.4 KiB
Haskell

module Hasura.Server.Middleware where
import Network.Wai
import Control.Applicative
import Hasura.Prelude
import Hasura.Server.Cors
import Hasura.Server.Utils
import qualified Data.ByteString as B
import qualified Data.CaseInsensitive as CI
import qualified Data.Text.Encoding as TE
import qualified Network.HTTP.Types as H
corsMiddleware :: CorsPolicy -> Middleware
corsMiddleware policy app req sendResp = do
let origin = getRequestHeader "Origin" $ requestHeaders req
maybe (app req sendResp) handleCors origin
where
handleCors origin = case cpConfig policy of
CCDisabled _ -> app req sendResp
CCAllowAll -> sendCors origin
CCAllowedOrigins ds
-- if the origin is in our cors domains, send cors headers
| bsToTxt origin `elem` dmFqdns ds -> sendCors origin
-- if current origin is part of wildcard domain list, send cors
| inWildcardList ds (bsToTxt origin) -> sendCors origin
-- otherwise don't send cors headers
| otherwise -> app req sendResp
sendCors :: B.ByteString -> IO ResponseReceived
sendCors origin =
case requestMethod req of
"OPTIONS" -> sendResp $ respondPreFlight origin
_ -> app req $ sendResp . injectCorsHeaders origin
respondPreFlight :: B.ByteString -> Response
respondPreFlight origin =
setHeaders (mkPreFlightHeaders requestedHeaders)
$ injectCorsHeaders origin emptyResponse
emptyResponse = responseLBS H.status204 [] ""
requestedHeaders =
fromMaybe "" $ getRequestHeader "Access-Control-Request-Headers" $
requestHeaders req
injectCorsHeaders :: B.ByteString -> Response -> Response
injectCorsHeaders origin = setHeaders (mkCorsHeaders origin)
mkPreFlightHeaders allowReqHdrs =
[ ("Access-Control-Max-Age", "1728000")
, ("Access-Control-Allow-Headers", allowReqHdrs)
, ("Content-Length", "0")
, ("Content-Type", "text/plain charset=UTF-8")
]
mkCorsHeaders origin =
[ ("Access-Control-Allow-Origin", origin)
, ("Access-Control-Allow-Credentials", "true")
, ("Access-Control-Allow-Methods",
B.intercalate "," $ TE.encodeUtf8 <$> cpMethods policy)
]
setHeaders hdrs = mapResponseHeaders (\h -> mkRespHdrs hdrs ++ h)
mkRespHdrs = map (\(k,v) -> (CI.mk k, v))