2021-11-04 19:08:33 +03:00
|
|
|
module Hasura.Server.Middleware
|
|
|
|
( corsMiddleware,
|
|
|
|
)
|
|
|
|
where
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2019-02-14 08:58:38 +03:00
|
|
|
import Control.Applicative
|
2019-07-11 08:37:06 +03:00
|
|
|
import Data.ByteString qualified as B
|
|
|
|
import Data.CaseInsensitive qualified as CI
|
|
|
|
import Data.Text.Encoding qualified as TE
|
2018-06-27 16:11:32 +03:00
|
|
|
import Hasura.Prelude
|
2019-02-14 08:58:38 +03:00
|
|
|
import Hasura.Server.Cors
|
|
|
|
import Hasura.Server.Utils
|
2022-02-16 10:08:51 +03:00
|
|
|
import Network.HTTP.Types qualified as HTTP
|
2018-06-27 16:11:32 +03:00
|
|
|
import Network.Wai
|
|
|
|
|
2023-03-17 13:29:07 +03:00
|
|
|
corsMiddleware :: IO CorsPolicy -> Middleware
|
|
|
|
corsMiddleware getPolicy app req sendResp = do
|
2019-07-11 08:37:06 +03:00
|
|
|
let origin = getRequestHeader "Origin" $ requestHeaders req
|
2023-03-17 13:29:07 +03:00
|
|
|
policy <- getPolicy
|
|
|
|
maybe (app req sendResp) (handleCors policy) origin
|
2018-06-27 16:11:32 +03:00
|
|
|
where
|
2023-03-17 13:29:07 +03:00
|
|
|
handleCors policy origin = case cpConfig policy of
|
2019-03-04 10:46:53 +03:00
|
|
|
CCDisabled _ -> app req sendResp
|
2023-03-17 13:29:07 +03:00
|
|
|
CCAllowAll -> sendCors origin policy
|
2019-02-14 08:58:38 +03:00
|
|
|
CCAllowedOrigins ds
|
|
|
|
-- if the origin is in our cors domains, send cors headers
|
2023-03-17 13:29:07 +03:00
|
|
|
| bsToTxt origin `elem` dmFqdns ds -> sendCors origin policy
|
2019-02-14 08:58:38 +03:00
|
|
|
-- if current origin is part of wildcard domain list, send cors
|
2023-03-17 13:29:07 +03:00
|
|
|
| inWildcardList ds (bsToTxt origin) -> sendCors origin policy
|
2019-02-14 08:58:38 +03:00
|
|
|
-- otherwise don't send cors headers
|
|
|
|
| otherwise -> app req sendResp
|
|
|
|
|
2023-03-17 13:29:07 +03:00
|
|
|
sendCors :: B.ByteString -> CorsPolicy -> IO ResponseReceived
|
|
|
|
sendCors origin policy =
|
2019-02-14 08:58:38 +03:00
|
|
|
case requestMethod req of
|
2023-03-17 13:29:07 +03:00
|
|
|
"OPTIONS" -> sendResp $ respondPreFlight origin policy
|
|
|
|
_ -> app req $ sendResp . injectCorsHeaders origin policy
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2023-03-17 13:29:07 +03:00
|
|
|
respondPreFlight :: B.ByteString -> CorsPolicy -> Response
|
|
|
|
respondPreFlight origin policy =
|
2018-06-27 16:11:32 +03:00
|
|
|
setHeaders (mkPreFlightHeaders requestedHeaders) $
|
2023-03-17 13:29:07 +03:00
|
|
|
injectCorsHeaders origin policy emptyResponse
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2022-02-16 10:08:51 +03:00
|
|
|
emptyResponse = responseLBS HTTP.status204 [] ""
|
2018-06-27 16:11:32 +03:00
|
|
|
requestedHeaders =
|
2019-07-11 08:37:06 +03:00
|
|
|
fromMaybe "" $
|
|
|
|
getRequestHeader "Access-Control-Request-Headers" $
|
|
|
|
requestHeaders req
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2023-03-17 13:29:07 +03:00
|
|
|
injectCorsHeaders :: B.ByteString -> CorsPolicy -> Response -> Response
|
|
|
|
injectCorsHeaders origin policy = setHeaders (mkCorsHeaders origin policy)
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
mkPreFlightHeaders allowReqHdrs =
|
|
|
|
[ ("Access-Control-Max-Age", "1728000"),
|
|
|
|
("Access-Control-Allow-Headers", allowReqHdrs),
|
|
|
|
("Content-Length", "0"),
|
|
|
|
("Content-Type", "text/plain charset=UTF-8")
|
|
|
|
]
|
|
|
|
|
2023-03-17 13:29:07 +03:00
|
|
|
mkCorsHeaders origin policy =
|
2018-06-27 16:11:32 +03:00
|
|
|
[ ("Access-Control-Allow-Origin", origin),
|
|
|
|
("Access-Control-Allow-Credentials", "true"),
|
|
|
|
( "Access-Control-Allow-Methods",
|
|
|
|
B.intercalate "," $ TE.encodeUtf8 <$> cpMethods policy
|
2023-04-16 22:31:59 +03:00
|
|
|
),
|
|
|
|
-- console requires this header to access the cache headers as HGE and console
|
|
|
|
-- are hosted on different domains in production
|
|
|
|
( "Access-Control-Expose-Headers",
|
|
|
|
B.intercalate "," $ TE.encodeUtf8 <$> cacheExposedHeaders
|
2018-06-27 16:11:32 +03:00
|
|
|
)
|
|
|
|
]
|
|
|
|
|
2023-04-16 22:31:59 +03:00
|
|
|
cacheExposedHeaders = ["X-Hasura-Query-Cache-Key", "X-Hasura-Query-Family-Cache-Key", "Warning"]
|
2018-06-27 16:11:32 +03:00
|
|
|
setHeaders hdrs = mapResponseHeaders (\h -> mkRespHdrs hdrs ++ h)
|
|
|
|
mkRespHdrs = map (\(k, v) -> (CI.mk k, v))
|