fix: no empty transaction on OPTIONS request
This commit is contained in:
committed by
Steve Chavez
parent
c445105d55
commit
4ab5e63e58
@@ -57,6 +57,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- #2341, The search path now correctly identifies schemas with uppercase and special characters in their names (regression) - @laurenceisla
|
- #2341, The search path now correctly identifies schemas with uppercase and special characters in their names (regression) - @laurenceisla
|
||||||
- #2364, "404 Not Found" on nested routes and "405 Method Not Allowed" errors no longer start an empty database transaction - @steve-chavez
|
- #2364, "404 Not Found" on nested routes and "405 Method Not Allowed" errors no longer start an empty database transaction - @steve-chavez
|
||||||
- #2342, Fix inaccurate result count when an inner embed was selected after a normal embed in the query string - @laurenceisla
|
- #2342, Fix inaccurate result count when an inner embed was selected after a normal embed in the query string - @laurenceisla
|
||||||
|
- #2376, OPTIONS requests no longer start an empty database transaction - @steve-chavez
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
+10
-7
@@ -206,11 +206,14 @@ postgrestResponse conf@AppConfig{..} maybeDbStructure jsonDbS pgVer pool AuthRes
|
|||||||
liftEither . mapLeft Error.ApiRequestError $
|
liftEither . mapLeft Error.ApiRequestError $
|
||||||
ApiRequest.userApiRequest conf dbStructure req body
|
ApiRequest.userApiRequest conf dbStructure req body
|
||||||
|
|
||||||
let handleReq apiReq = handleRequest $ RequestContext conf dbStructure apiReq pgVer
|
let ctx apiReq = RequestContext conf dbStructure apiReq pgVer
|
||||||
|
|
||||||
|
if iAction apiRequest == ActionInfo then
|
||||||
|
handleInfo (iTarget apiRequest) (ctx apiRequest)
|
||||||
|
else
|
||||||
runDbHandler pool (txMode apiRequest) (Just authRole /= configDbAnonRole) configDbPreparedStatements .
|
runDbHandler pool (txMode apiRequest) (Just authRole /= configDbAnonRole) configDbPreparedStatements .
|
||||||
Middleware.optionalRollback conf apiRequest $
|
Middleware.optionalRollback conf apiRequest $
|
||||||
Middleware.runPgLocals conf authClaims authRole handleReq apiRequest jsonDbS pgVer
|
Middleware.runPgLocals conf authClaims authRole (handleRequest . ctx) apiRequest jsonDbS pgVer
|
||||||
|
|
||||||
runDbHandler :: SQL.Pool -> SQL.Mode -> Bool -> Bool -> DbHandler a -> Handler IO a
|
runDbHandler :: SQL.Pool -> SQL.Mode -> Bool -> Bool -> DbHandler a -> Handler IO a
|
||||||
runDbHandler pool mode authenticated prepared handler = do
|
runDbHandler pool mode authenticated prepared handler = do
|
||||||
@@ -237,8 +240,6 @@ handleRequest context@(RequestContext _ _ ApiRequest{..} _) =
|
|||||||
handleSingleUpsert identifier context
|
handleSingleUpsert identifier context
|
||||||
(ActionMutate MutationDelete, TargetIdent identifier) ->
|
(ActionMutate MutationDelete, TargetIdent identifier) ->
|
||||||
handleDelete identifier context
|
handleDelete identifier context
|
||||||
(ActionInfo, TargetIdent identifier) ->
|
|
||||||
handleInfo identifier context
|
|
||||||
(ActionInvoke invMethod, TargetProc proc _) ->
|
(ActionInvoke invMethod, TargetProc proc _) ->
|
||||||
handleInvoke invMethod proc context
|
handleInvoke invMethod proc context
|
||||||
(ActionInspect headersOnly, TargetDefaultSpec tSchema) ->
|
(ActionInspect headersOnly, TargetDefaultSpec tSchema) ->
|
||||||
@@ -414,8 +415,8 @@ handleDelete identifier context@(RequestContext _ _ ApiRequest{..} _) = do
|
|||||||
else
|
else
|
||||||
response HTTP.status204 [contentRangeHeader] mempty)
|
response HTTP.status204 [contentRangeHeader] mempty)
|
||||||
|
|
||||||
handleInfo :: Monad m => QualifiedIdentifier -> RequestContext -> Handler m Wai.Response
|
handleInfo :: Monad m => Target -> RequestContext -> Handler m Wai.Response
|
||||||
handleInfo identifier RequestContext{..} =
|
handleInfo target RequestContext{..} =
|
||||||
case tbl of
|
case tbl of
|
||||||
Just table ->
|
Just table ->
|
||||||
return $ Wai.responseLBS HTTP.status200 [allOrigins, allowH table] mempty
|
return $ Wai.responseLBS HTTP.status200 [allOrigins, allowH table] mempty
|
||||||
@@ -423,7 +424,9 @@ handleInfo identifier RequestContext{..} =
|
|||||||
-- TODO is this right? When no tbl is found on the schema cache we disallow OPTIONS?
|
-- TODO is this right? When no tbl is found on the schema cache we disallow OPTIONS?
|
||||||
throwError $ Error.ApiRequestError ApiRequestTypes.NotFound
|
throwError $ Error.ApiRequestError ApiRequestTypes.NotFound
|
||||||
where
|
where
|
||||||
tbl = HM.lookup identifier (dbTables ctxDbStructure)
|
tbl = case target of
|
||||||
|
TargetIdent identifier -> HM.lookup identifier (dbTables ctxDbStructure)
|
||||||
|
_ -> Nothing
|
||||||
allOrigins = ("Access-Control-Allow-Origin", "*")
|
allOrigins = ("Access-Control-Allow-Origin", "*")
|
||||||
allowH table =
|
allowH table =
|
||||||
( HTTP.hAllow
|
( HTTP.hAllow
|
||||||
|
|||||||
@@ -972,6 +972,33 @@ def test_no_pool_connection_required_on_bad_http_logic(defaultenv):
|
|||||||
assert response.status_code == 405
|
assert response.status_code == 405
|
||||||
|
|
||||||
|
|
||||||
|
def test_no_pool_connection_required_on_options(defaultenv):
|
||||||
|
"no pool connection should be consumed for OPTIONS requests"
|
||||||
|
|
||||||
|
env = {
|
||||||
|
**defaultenv,
|
||||||
|
"PGRST_DB_POOL": "1",
|
||||||
|
}
|
||||||
|
|
||||||
|
with run(env=env) as postgrest:
|
||||||
|
# First we retain the only pool connection available
|
||||||
|
# The try/except is a hack for not waiting for the response, taken from https://stackoverflow.com/a/45601591/4692662
|
||||||
|
try:
|
||||||
|
postgrest.session.get("/rpc/sleep?seconds=50", timeout=0.1)
|
||||||
|
except requests.exceptions.ReadTimeout:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Then the following OPTIONS requests should succeed rapidly
|
||||||
|
|
||||||
|
# OPTIONS on a table shouldn't require opening a connection
|
||||||
|
response = postgrest.session.options("/projects")
|
||||||
|
assert response.status_code == 200
|
||||||
|
|
||||||
|
# OPTIONS on RPC is not implemented yet, still it shouldn't require opening a connection
|
||||||
|
response = postgrest.session.options("/rpc/hello")
|
||||||
|
assert response.status_code == 405
|
||||||
|
|
||||||
|
|
||||||
def test_no_pool_connection_required_on_bad_jwt_claim(defaultenv):
|
def test_no_pool_connection_required_on_bad_jwt_claim(defaultenv):
|
||||||
"no pool connection should be consumed for failing on invalid jwt"
|
"no pool connection should be consumed for failing on invalid jwt"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user