Skip to content

Commit 20b6af8

Browse files
committed
feat: add config to specify CORS origins
1 parent 618f93d commit 20b6af8

18 files changed

+90
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
1313
- #2698, Add config `jwt-cache-max-lifetime` and implement JWT caching - @taimoorzaeem
1414
- #2943, Add `handling=strict/lenient` for Prefer header - @taimoorzaeem
1515
- #2983, Add more data to `Server-Timing` header - @develop7
16+
- #2441, Add config `cors-allowed-origins` to specify CORS origins - @taimoorzaeem
1617

1718
### Fixed
1819

src/PostgREST/App.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ serverSettings AppConfig{..} =
110110
postgrest :: AppConfig -> AppState.AppState -> IO () -> Wai.Application
111111
postgrest conf appState connWorker =
112112
traceHeaderMiddleware conf .
113-
Cors.middleware .
113+
Cors.middleware (configCorsAllowedOrigins conf) .
114114
Auth.middleware appState .
115115
Logger.middleware (configLogLevel conf) $
116116
-- fromJust can be used, because the auth middleware will **always** add

src/PostgREST/CLI.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ exampleConfigFile =
126126
[str|## Admin server used for checks. It's disabled by default unless a port is specified.
127127
|# admin-server-port = 3001
128128
|
129+
|## Configurable CORS origins
130+
|# cors-allowed-origins = "*"
131+
|
129132
|## The database role to use when no client authentication is provided
130133
|# db-anon-role = "anon"
131134
|

src/PostgREST/Config.hs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ import Protolude hiding (Proxy, toList)
7070

7171
data AppConfig = AppConfig
7272
{ configAppSettings :: [(Text, Text)]
73+
, configCorsAllowedOrigins :: Maybe [Text]
7374
, configDbAnonRole :: Maybe BS.ByteString
7475
, configDbChannel :: Text
7576
, configDbChannelEnabled :: Bool
@@ -139,7 +140,8 @@ toText conf =
139140
where
140141
-- apply conf to all pgrst settings
141142
pgrstSettings = (\(k, v) -> (k, v conf)) <$>
142-
[("db-anon-role", q . T.decodeUtf8 . fromMaybe "" . configDbAnonRole)
143+
[("cors-allowed-origins", q . maybe "*" (T.intercalate ",") . configCorsAllowedOrigins)
144+
,("db-anon-role", q . T.decodeUtf8 . fromMaybe "" . configDbAnonRole)
143145
,("db-channel", q . configDbChannel)
144146
,("db-channel-enabled", T.toLower . show . configDbChannelEnabled)
145147
,("db-extra-search-path", q . T.intercalate "," . configDbExtraSearchPath)
@@ -233,6 +235,7 @@ parser :: Maybe FilePath -> Environment -> [(Text, Text)] -> RoleSettings -> Rol
233235
parser optPath env dbSettings roleSettings roleIsolationLvl =
234236
AppConfig
235237
<$> parseAppSettings "app.settings"
238+
<*> (fmap splitOnCommas <$> optValue "cors-allowed-origins")
236239
<*> (fmap encodeUtf8 <$> optString "db-anon-role")
237240
<*> (fromMaybe "pgrst" <$> optString "db-channel")
238241
<*> (fromMaybe True <$> optBool "db-channel-enabled")

src/PostgREST/Cors.hs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,30 @@
22
Module : PostgREST.Cors
33
Description : Wai Middleware to set cors policy.
44
-}
5+
6+
{-# LANGUAGE TupleSections #-}
7+
58
module PostgREST.Cors (middleware) where
69

710
import qualified Data.ByteString.Char8 as BS
811
import qualified Data.CaseInsensitive as CI
12+
import qualified Data.Text.Encoding as T
913
import qualified Network.Wai as Wai
1014
import qualified Network.Wai.Middleware.Cors as Wai
1115

1216
import Data.List (lookup)
1317

1418
import Protolude
1519

16-
middleware :: Wai.Middleware
17-
middleware = Wai.cors corsPolicy
20+
middleware :: Maybe [Text] -> Wai.Middleware
21+
middleware corsAllowedOrigins = Wai.cors $ corsPolicy corsAllowedOrigins
1822

1923
-- | CORS policy to be used in by Wai Cors middleware
20-
corsPolicy :: Wai.Request -> Maybe Wai.CorsResourcePolicy
21-
corsPolicy req = case lookup "origin" headers of
22-
Just origin ->
24+
corsPolicy :: Maybe [Text] -> Wai.Request -> Maybe Wai.CorsResourcePolicy
25+
corsPolicy corsAllowedOrigins req = case lookup "origin" headers of
26+
Just _ ->
2327
Just Wai.CorsResourcePolicy
24-
{ Wai.corsOrigins = Just ([origin], True)
28+
{ Wai.corsOrigins = (, True) . map T.encodeUtf8 <$> corsAllowedOrigins
2529
, Wai.corsMethods = ["GET", "POST", "PATCH", "PUT", "DELETE", "OPTIONS"]
2630
, Wai.corsRequestHeaders = "Authorization" : accHeaders
2731
, Wai.corsExposedHeaders = Just

test/io/configs/expected/aliases.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
cors-allowed-origins = "*"
12
db-anon-role = ""
23
db-channel = "pgrst"
34
db-channel-enabled = true

test/io/configs/expected/boolean-numeric.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
cors-allowed-origins = "*"
12
db-anon-role = ""
23
db-channel = "pgrst"
34
db-channel-enabled = true

test/io/configs/expected/boolean-string.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
cors-allowed-origins = "*"
12
db-anon-role = ""
23
db-channel = "pgrst"
34
db-channel-enabled = true

test/io/configs/expected/defaults.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
cors-allowed-origins = "*"
12
db-anon-role = ""
23
db-channel = "pgrst"
34
db-channel-enabled = true

test/io/configs/expected/no-defaults-with-db-other-authenticator.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
cors-allowed-origins = "http://example.com"
12
db-anon-role = "pre_config_role"
23
db-channel = "postgrest"
34
db-channel-enabled = false

0 commit comments

Comments
 (0)