feat: implement server-timing-enabled config parameter (#3064)

This commit is contained in:
Andrei Dziahel
2023-11-22 17:57:50 -05:00
committed by GitHub
parent abcb21c69a
commit c3301a1653
18 changed files with 26 additions and 8 deletions
+1
View File
@@ -19,6 +19,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- #2799, Add timezone in Prefer header - @taimoorzaeem
- #3001, Add `statement_timeout` set on functions - @taimoorzaeem
- #3045, Apply superuser settings on impersonated roles if they have PostgreSQL 15 `GRANT SET ON PARAMETER` privilege - @steve-chavez
- #3062, Add config for enabling the `Server-Timing` header - @develop7
### Fixed
+3 -3
View File
@@ -159,7 +159,7 @@ postgrestResponse appState conf@AppConfig{..} maybeSchemaCache pgVer authResult@
liftEither . mapLeft Error.ApiRequestError $
ApiRequest.userApiRequest conf req body sCache
let jwtTiming = (SMJwt, if configDbPlanEnabled then Auth.getJwtDur req else Nothing)
let jwtTiming = (SMJwt, if configServerTimingEnabled then Auth.getJwtDur req else Nothing)
handleRequest authResult conf appState (Just authRole /= configDbAnonRole) configDbPreparedStatements pgVer apiRequest sCache jwtTiming
runDbHandler :: AppState.AppState -> SQL.IsolationLevel -> SQL.Mode -> Bool -> Bool -> DbHandler b -> Handler IO b
@@ -256,9 +256,9 @@ handleRequest AuthResult{..} conf appState authenticated prepared pgVer apiReq@A
query
pgrstResponse :: ServerTimingData -> Response.PgrstResponse -> Wai.Response
pgrstResponse timings (Response.PgrstResponse st hdrs bod) = Wai.responseLBS st (hdrs ++ ([renderServerTimingHeader timings | configDbPlanEnabled conf])) bod
pgrstResponse timings (Response.PgrstResponse st hdrs bod) = Wai.responseLBS st (hdrs ++ ([renderServerTimingHeader timings | configServerTimingEnabled conf])) bod
withTiming f = if configDbPlanEnabled conf
withTiming f = if configServerTimingEnabled conf
then do
(t, r) <- timeItT f
pure (Just t, r)
+1 -1
View File
@@ -109,7 +109,7 @@ middleware appState app req respond = do
-- If DbPlanEnabled -> calculate JWT validation time
-- If JwtCacheMaxLifetime -> cache JWT validation result
req' <- case (configDbPlanEnabled conf, configJwtCacheMaxLifetime conf) of
req' <- case (configServerTimingEnabled conf, configJwtCacheMaxLifetime conf) of
(True, 0) -> do
(dur, authResult) <- timeItT parseJwt
return $ req { Wai.vault = Wai.vault req & Vault.insert authResultKey authResult & Vault.insert jwtDurKey dur }
+3
View File
@@ -104,6 +104,7 @@ data AppConfig = AppConfig
, configServerHost :: Text
, configServerPort :: Int
, configServerTraceHeader :: Maybe (CI.CI BS.ByteString)
, configServerTimingEnabled :: Bool
, configServerUnixSocket :: Maybe FilePath
, configServerUnixSocketMode :: FileMode
, configAdminServerPort :: Maybe Int
@@ -169,6 +170,7 @@ toText conf =
,("server-host", q . configServerHost)
,("server-port", show . configServerPort)
,("server-trace-header", q . T.decodeUtf8 . maybe mempty CI.original . configServerTraceHeader)
,("server-timing-enabled", T.toLower . show . configServerTimingEnabled)
,("server-unix-socket", q . maybe mempty T.pack . configServerUnixSocket)
,("server-unix-socket-mode", q . T.pack . showSocketMode)
,("admin-server-port", maybe "\"\"" show . configAdminServerPort)
@@ -272,6 +274,7 @@ parser optPath env dbSettings roleSettings roleIsolationLvl =
<*> (fromMaybe "!4" <$> optString "server-host")
<*> (fromMaybe 3000 <$> optInt "server-port")
<*> (fmap (CI.mk . encodeUtf8) <$> optString "server-trace-header")
<*> (fromMaybe False <$> optBool "server-timing-enabled")
<*> (fmap T.unpack <$> optString "server-unix-socket")
<*> parseSocketFileMode "server-unix-socket-mode"
<*> optInt "admin-server-port"
+1
View File
@@ -64,6 +64,7 @@ dbSettingsNames =
,"openapi_server_proxy_uri"
,"raw_media_types"
,"server_trace_header"
,"server_timing_enabled"
]
queryPgVersion :: Bool -> Session PgVersion
+1
View File
@@ -30,6 +30,7 @@ server-cors-allowed-origins = ""
server-host = "!4"
server-port = 3000
server-trace-header = ""
server-timing-enabled = false
server-unix-socket = ""
server-unix-socket-mode = "660"
admin-server-port = ""
@@ -30,6 +30,7 @@ server-cors-allowed-origins = ""
server-host = "!4"
server-port = 3000
server-trace-header = ""
server-timing-enabled = false
server-unix-socket = ""
server-unix-socket-mode = "660"
admin-server-port = ""
@@ -30,6 +30,7 @@ server-cors-allowed-origins = ""
server-host = "!4"
server-port = 3000
server-trace-header = ""
server-timing-enabled = false
server-unix-socket = ""
server-unix-socket-mode = "660"
admin-server-port = ""
+1
View File
@@ -30,6 +30,7 @@ server-cors-allowed-origins = ""
server-host = "!4"
server-port = 3000
server-trace-header = ""
server-timing-enabled = false
server-unix-socket = ""
server-unix-socket-mode = "660"
admin-server-port = ""
@@ -30,6 +30,7 @@ server-cors-allowed-origins = "http://example.com"
server-host = "0.0.0.0"
server-port = 80
server-trace-header = "traceparent"
server-timing-enabled = true
server-unix-socket = "/tmp/pgrst_io_test.sock"
server-unix-socket-mode = "777"
admin-server-port = 3001
@@ -30,6 +30,7 @@ server-cors-allowed-origins = "http://example.com"
server-host = "0.0.0.0"
server-port = 80
server-trace-header = "CF-Ray"
server-timing-enabled = true
server-unix-socket = "/tmp/pgrst_io_test.sock"
server-unix-socket-mode = "777"
admin-server-port = 3001
@@ -30,6 +30,7 @@ server-cors-allowed-origins = "http://example.com"
server-host = "0.0.0.0"
server-port = 80
server-trace-header = "X-Request-Id"
server-timing-enabled = true
server-unix-socket = "/tmp/pgrst_io_test.sock"
server-unix-socket-mode = "777"
admin-server-port = 3001
+1
View File
@@ -30,6 +30,7 @@ server-cors-allowed-origins = ""
server-host = "!4"
server-port = 3000
server-trace-header = ""
server-timing-enabled = false
server-unix-socket = ""
server-unix-socket-mode = "660"
admin-server-port = ""
+1
View File
@@ -33,6 +33,7 @@ PGRST_SERVER_CORS_ALLOWED_ORIGINS: "http://example.com"
PGRST_SERVER_HOST: 0.0.0.0
PGRST_SERVER_PORT: 80
PGRST_SERVER_TRACE_HEADER: X-Request-Id
PGRST_SERVER_TIMING_ENABLED: true
PGRST_SERVER_UNIX_SOCKET: /tmp/pgrst_io_test.sock
PGRST_SERVER_UNIX_SOCKET_MODE: 777
PGRST_ADMIN_SERVER_PORT: 3001
+1
View File
@@ -30,6 +30,7 @@ server-cors-allowed-origins = "http://example.com"
server-host = "0.0.0.0"
server-port = 80
server-trace-header = "X-Request-Id"
server-timing-enabled = true
server-unix-socket = "/tmp/pgrst_io_test.sock"
server-unix-socket-mode = "777"
admin-server-port = 3001
+2
View File
@@ -19,6 +19,7 @@ ALTER ROLE db_config_authenticator SET pgrst.db_extra_search_path = 'public, ext
ALTER ROLE db_config_authenticator SET pgrst.not_existing = 'should be ignored';
ALTER ROLE db_config_authenticator SET pgrst.server_cors_allowed_origins = 'http://example.com';
ALTER ROLE db_config_authenticator SET pgrst.server_trace_header = 'CF-Ray';
ALTER ROLE db_config_authenticator SET pgrst.server_timing_enabled = 'true';
-- override with database specific setting
ALTER ROLE db_config_authenticator IN DATABASE :DBNAME SET pgrst.jwt_secret = 'OVERRIDE=REALLY=REALLY=REALLY=REALLY=VERY=SAFE';
@@ -64,6 +65,7 @@ ALTER ROLE other_authenticator SET pgrst.openapi_security_active = 'false';
ALTER ROLE other_authenticator SET pgrst.server_cors_allowed_origins = 'http://example.com';
ALTER ROLE other_authenticator SET pgrst.server_trace_header = 'traceparent';
ALTER ROLE other_authenticator SET pgrst.db_pre_config = 'postgrest.pre_config';
ALTER ROLE other_authenticator SET pgrst.server_timing_enabled = 'true';
create schema postgrest;
grant usage on schema postgrest to db_config_authenticator;
+4 -4
View File
@@ -1120,7 +1120,7 @@ def test_server_timing_jwt_should_decrease_on_subsequent_requests(defaultenv):
env = {
**defaultenv,
"PGRST_DB_PLAN_ENABLED": "true",
"PGRST_SERVER_TIMING_ENABLED": "true",
"PGRST_JWT_CACHE_MAX_LIFETIME": "86400",
"PGRST_JWT_SECRET": "@/dev/stdin",
"PGRST_DB_CONFIG": "false",
@@ -1158,7 +1158,7 @@ def test_jwt_caching_works_with_db_plan_disabled(defaultenv):
env = {
**defaultenv,
"PGRST_DB_PLAN_ENABLED": "false",
"PGRST_SERVER_TIMING_ENABLED": "true",
"PGRST_JWT_CACHE_MAX_LIFETIME": "86400",
"PGRST_JWT_SECRET": "@/dev/stdin",
"PGRST_DB_CONFIG": "false",
@@ -1180,7 +1180,7 @@ def test_server_timing_jwt_should_not_decrease_when_caching_disabled(defaultenv)
env = {
**defaultenv,
"PGRST_DB_PLAN_ENABLED": "true",
"PGRST_SERVER_TIMING_ENABLED": "true",
"PGRST_JWT_CACHE_MAX_LIFETIME": "0", # cache disabled
"PGRST_JWT_SECRET": "@/dev/stdin",
"PGRST_DB_CONFIG": "false",
@@ -1210,7 +1210,7 @@ def test_jwt_cache_with_no_exp_claim(defaultenv):
env = {
**defaultenv,
"PGRST_DB_PLAN_ENABLED": "true",
"PGRST_SERVER_TIMING_ENABLED": "true",
"PGRST_JWT_CACHE_MAX_LIFETIME": "86400",
"PGRST_JWT_SECRET": "@/dev/stdin",
"PGRST_DB_CONFIG": "false",
+1
View File
@@ -139,6 +139,7 @@ baseCfg = let secret = Just $ encodeUtf8 "reallyreallyreallyreallyverysafe" in
, configRoleSettings = mempty
, configRoleIsoLvl = mempty
, configInternalSCSleep = Nothing
, configServerTimingEnabled = True
}
testCfg :: AppConfig