feat: improve error response when the requested schema is invalid
- It now shows the invalid schema in the "message" - The exposed schemas are now listed in the "hint" instead of the "message"
This commit is contained in:
committed by
Steve Chavez
parent
a4927141ee
commit
4ba6b1b30c
@@ -5,6 +5,12 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Improve the `PGRST106` error when the requested schema is invalid by @laurenceisla in #4089
|
||||||
|
+ It now shows the invalid schema in the `message` field.
|
||||||
|
+ The exposed schemas are now listed in the `hint` instead of the `message` field.
|
||||||
|
|
||||||
## [13.0.6] - 2025-08-30
|
## [13.0.6] - 2025-08-30
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ getAction resource schema method =
|
|||||||
getSchema :: AppConfig -> RequestHeaders -> ByteString -> Either ApiRequestError (Schema, Bool)
|
getSchema :: AppConfig -> RequestHeaders -> ByteString -> Either ApiRequestError (Schema, Bool)
|
||||||
getSchema AppConfig{configDbSchemas} hdrs method = do
|
getSchema AppConfig{configDbSchemas} hdrs method = do
|
||||||
case profile of
|
case profile of
|
||||||
Just p | p `notElem` configDbSchemas -> Left $ UnacceptableSchema $ toList configDbSchemas
|
Just p | p `notElem` configDbSchemas -> Left $ UnacceptableSchema p $ toList configDbSchemas
|
||||||
| otherwise -> Right (p, True)
|
| otherwise -> Right (p, True)
|
||||||
Nothing -> Right (defaultSchema, length configDbSchemas /= 1) -- if we have many schemas, assume the default schema was negotiated
|
Nothing -> Right (defaultSchema, length configDbSchemas /= 1) -- if we have many schemas, assume the default schema was negotiated
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ data ApiRequestError
|
|||||||
| QueryParamError QPError
|
| QueryParamError QPError
|
||||||
| RelatedOrderNotToOne Text Text
|
| RelatedOrderNotToOne Text Text
|
||||||
| UnacceptableFilter Text
|
| UnacceptableFilter Text
|
||||||
| UnacceptableSchema [Text]
|
| UnacceptableSchema Text [Text]
|
||||||
| UnsupportedMethod ByteString
|
| UnsupportedMethod ByteString
|
||||||
| GucHeadersError
|
| GucHeadersError
|
||||||
| GucStatusError
|
| GucStatusError
|
||||||
@@ -194,7 +194,7 @@ instance ErrorBody ApiRequestError where
|
|||||||
message (InvalidBody errorMessage) = T.decodeUtf8 errorMessage
|
message (InvalidBody errorMessage) = T.decodeUtf8 errorMessage
|
||||||
message (InvalidRange _) = "Requested range not satisfiable"
|
message (InvalidRange _) = "Requested range not satisfiable"
|
||||||
message InvalidFilters = "Filters must include all and only primary key columns with 'eq' operators"
|
message InvalidFilters = "Filters must include all and only primary key columns with 'eq' operators"
|
||||||
message (UnacceptableSchema schemas) = "The schema must be one of the following: " <> T.intercalate ", " schemas
|
message (UnacceptableSchema sch _) = "Invalid schema: " <> sch
|
||||||
message (MediaTypeError cts) = "None of these media types are available: " <> T.intercalate ", " (map T.decodeUtf8 cts)
|
message (MediaTypeError cts) = "None of these media types are available: " <> T.intercalate ", " (map T.decodeUtf8 cts)
|
||||||
message (NotEmbedded resource) = "'" <> resource <> "' is not an embedded resource in this request"
|
message (NotEmbedded resource) = "'" <> resource <> "' is not an embedded resource in this request"
|
||||||
message GucHeadersError = "response.headers guc must be a JSON array composed of objects with a single key and a string value"
|
message GucHeadersError = "response.headers guc must be a JSON array composed of objects with a single key and a string value"
|
||||||
@@ -234,6 +234,7 @@ instance ErrorBody ApiRequestError where
|
|||||||
-- HINT: Maybe JSON.Value
|
-- HINT: Maybe JSON.Value
|
||||||
hint (NotEmbedded resource) = Just $ JSON.String $ "Verify that '" <> resource <> "' is included in the 'select' query parameter."
|
hint (NotEmbedded resource) = Just $ JSON.String $ "Verify that '" <> resource <> "' is included in the 'select' query parameter."
|
||||||
hint (PGRSTParseError raiseErr) = Just $ JSON.String $ pgrstParseErrorHint raiseErr
|
hint (PGRSTParseError raiseErr) = Just $ JSON.String $ pgrstParseErrorHint raiseErr
|
||||||
|
hint (UnacceptableSchema _ schemas) = Just $ JSON.String $ "Only the following schemas are exposed: " <> T.intercalate ", " schemas
|
||||||
|
|
||||||
hint _ = Nothing
|
hint _ = Nothing
|
||||||
|
|
||||||
|
|||||||
@@ -72,9 +72,9 @@ spec =
|
|||||||
, matchHeaders = []
|
, matchHeaders = []
|
||||||
}
|
}
|
||||||
|
|
||||||
it "fails trying to read table from unkown schema" $
|
it "fails trying to read table from unknown schema" $
|
||||||
request methodGet "/parents" [("Accept-Profile", "unkown")] "" `shouldRespondWith`
|
request methodGet "/parents" [("Accept-Profile", "unknown")] "" `shouldRespondWith`
|
||||||
[json|{"message":"The schema must be one of the following: v1, v2, SPECIAL \"@/\\#~_-","code":"PGRST106","details":null,"hint":null}|]
|
[json|{"message":"Invalid schema: unknown","code":"PGRST106","details":null,"hint":"Only the following schemas are exposed: v1, v2, SPECIAL \"@/\\#~_-"}|]
|
||||||
{
|
{
|
||||||
matchStatus = 406
|
matchStatus = 406
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ spec =
|
|||||||
request methodPost "/children" [("Content-Profile", "unknown")]
|
request methodPost "/children" [("Content-Profile", "unknown")]
|
||||||
[json|{"name": "child 4", "parent_id": 4}|]
|
[json|{"name": "child 4", "parent_id": 4}|]
|
||||||
`shouldRespondWith`
|
`shouldRespondWith`
|
||||||
[json|{"message":"The schema must be one of the following: v1, v2, SPECIAL \"@/\\#~_-","code":"PGRST106","details":null,"hint":null}|]
|
[json|{"message":"Invalid schema: unknown","code":"PGRST106","details":null,"hint":"Only the following schemas are exposed: v1, v2, SPECIAL \"@/\\#~_-"}|]
|
||||||
{
|
{
|
||||||
matchStatus = 406
|
matchStatus = 406
|
||||||
}
|
}
|
||||||
@@ -389,9 +389,9 @@ spec =
|
|||||||
let def = simpleBody r ^? key "definitions" . key "another_table"
|
let def = simpleBody r ^? key "definitions" . key "another_table"
|
||||||
def `shouldBe` Nothing
|
def `shouldBe` Nothing
|
||||||
|
|
||||||
it "fails trying to read definitions from unkown schema" $
|
it "fails trying to read definitions from unknown schema" $
|
||||||
request methodGet "/" [("Accept-Profile", "unkown")] "" `shouldRespondWith`
|
request methodGet "/" [("Accept-Profile", "unknown")] "" `shouldRespondWith`
|
||||||
[json|{"message":"The schema must be one of the following: v1, v2, SPECIAL \"@/\\#~_-","code":"PGRST106","details":null,"hint":null}|]
|
[json|{"message":"Invalid schema: unknown","code":"PGRST106","details":null,"hint":"Only the following schemas are exposed: v1, v2, SPECIAL \"@/\\#~_-"}|]
|
||||||
{
|
{
|
||||||
matchStatus = 406
|
matchStatus = 406
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user