mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
Data Connectors API 400 error response - GDC-619
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6839 GitOrigin-RevId: 813ea5e976ff41754e7500abf6bcd0c8b70c960e
This commit is contained in:
parent
6470eeb7f6
commit
6f9f44a441
@ -1513,7 +1513,7 @@ However, this endpoint can also be used to check whether the ability of the agen
|
|||||||
|
|
||||||
### Reporting Errors
|
### Reporting Errors
|
||||||
|
|
||||||
Any non-200 response code from an Agent (except for the `/health` endpoint) will be interpreted as an error. These should be handled gracefully by `graphql-engine` but provide limited details to users. If you wish to return structured error information to users you can return a status of `500` from the `/capabilities`, `/schema`, and `/query` endpoints with the following JSON format:
|
Any non-200 response code from an Agent (except for the `/health` endpoint) will be interpreted as an error. These should be handled gracefully by `graphql-engine` but provide limited details to users. If you wish to return structured error information to users you can return a status of `500`, or `400` from the `/capabilities`, `/schema`, and `/query` endpoints with the following JSON format:
|
||||||
|
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,7 @@ where
|
|||||||
import Control.Arrow (left)
|
import Control.Arrow (left)
|
||||||
import Data.ByteString.Lazy as BL
|
import Data.ByteString.Lazy as BL
|
||||||
import Data.Data (Proxy (..))
|
import Data.Data (Proxy (..))
|
||||||
|
import Data.Foldable (for_)
|
||||||
import Data.List.NonEmpty (NonEmpty ((:|)))
|
import Data.List.NonEmpty (NonEmpty ((:|)))
|
||||||
import Data.OpenApi (OpenApi)
|
import Data.OpenApi (OpenApi)
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
@ -47,12 +48,14 @@ capabilitiesCase :: a -> (CapabilitiesResponse -> a) -> (ErrorResponse -> a) ->
|
|||||||
capabilitiesCase defaultAction capabilitiesAction errorAction union = do
|
capabilitiesCase defaultAction capabilitiesAction errorAction union = do
|
||||||
let capabilitiesM = matchUnion @CapabilitiesResponse union
|
let capabilitiesM = matchUnion @CapabilitiesResponse union
|
||||||
let errorM = matchUnion @ErrorResponse union
|
let errorM = matchUnion @ErrorResponse union
|
||||||
case (capabilitiesM, errorM) of
|
let errorM400 = matchUnion @ErrorResponse400 union
|
||||||
(Just c, Nothing) -> capabilitiesAction c
|
case (capabilitiesM, errorM, errorM400) of
|
||||||
(Nothing, Just e) -> errorAction e
|
(Nothing, Nothing, Nothing) -> defaultAction
|
||||||
_ -> defaultAction -- Note, this could technically include the (Just _, Just _) scenario which is not possible.
|
(Just c, _, _) -> capabilitiesAction c
|
||||||
|
(_, Just e, _) -> errorAction e
|
||||||
|
(_, _, Just (WithStatus e)) -> errorAction e
|
||||||
|
|
||||||
type CapabilitiesResponses = '[V0.CapabilitiesResponse, V0.ErrorResponse]
|
type CapabilitiesResponses = '[V0.CapabilitiesResponse, V0.ErrorResponse, V0.ErrorResponse400]
|
||||||
|
|
||||||
type CapabilitiesApi =
|
type CapabilitiesApi =
|
||||||
"capabilities"
|
"capabilities"
|
||||||
@ -60,16 +63,19 @@ type CapabilitiesApi =
|
|||||||
|
|
||||||
-- | This function defines a central place to ensure that all cases are covered for schema and error responses.
|
-- | This function defines a central place to ensure that all cases are covered for schema and error responses.
|
||||||
-- When additional responses are added to the Union, this should be updated to ensure that all responses have been considered.
|
-- When additional responses are added to the Union, this should be updated to ensure that all responses have been considered.
|
||||||
schemaCase :: Monad m => m a -> (SchemaResponse -> m a) -> (ErrorResponse -> m a) -> Union SchemaResponses -> m a
|
schemaCase :: a -> (SchemaResponse -> a) -> (ErrorResponse -> a) -> Union SchemaResponses -> a
|
||||||
schemaCase defaultAction schemaAction errorAction union = do
|
schemaCase defaultAction schemaAction errorAction union = do
|
||||||
let schemaM = matchUnion @SchemaResponse union
|
let schemaM = matchUnion @SchemaResponse union
|
||||||
let errorM = matchUnion @ErrorResponse union
|
let errorM = matchUnion @ErrorResponse union
|
||||||
case (schemaM, errorM) of
|
let errorM400 = matchUnion @ErrorResponse400 union
|
||||||
(Just c, Nothing) -> schemaAction c
|
case (schemaM, errorM, errorM400) of
|
||||||
(Nothing, Just e) -> errorAction e
|
-- Note, this could technically include the ...Just _, Just _... scenario, but won't occurr due to matchUnion
|
||||||
_ -> defaultAction -- Note, this could technically include the (Just _, Just _) scenario which is not possible.
|
(Nothing, Nothing, Nothing) -> defaultAction
|
||||||
|
(Just x, _, _) -> schemaAction x
|
||||||
|
(_, Just x, _) -> errorAction x
|
||||||
|
(_, _, Just (WithStatus x)) -> errorAction x
|
||||||
|
|
||||||
type SchemaResponses = '[V0.SchemaResponse, V0.ErrorResponse]
|
type SchemaResponses = '[V0.SchemaResponse, V0.ErrorResponse, V0.ErrorResponse400]
|
||||||
|
|
||||||
type SchemaApi =
|
type SchemaApi =
|
||||||
"schema"
|
"schema"
|
||||||
@ -79,16 +85,18 @@ type SchemaApi =
|
|||||||
|
|
||||||
-- | This function defines a central place to ensure that all cases are covered for query and error responses.
|
-- | This function defines a central place to ensure that all cases are covered for query and error responses.
|
||||||
-- When additional responses are added to the Union, this should be updated to ensure that all responses have been considered.
|
-- When additional responses are added to the Union, this should be updated to ensure that all responses have been considered.
|
||||||
queryCase :: Monad m => m a -> (QueryResponse -> m a) -> (ErrorResponse -> m a) -> Union QueryResponses -> m a
|
queryCase :: a -> (QueryResponse -> a) -> (ErrorResponse -> a) -> Union QueryResponses -> a
|
||||||
queryCase defaultAction queryAction errorAction union = do
|
queryCase defaultAction queryAction errorAction union = do
|
||||||
let queryM = matchUnion @QueryResponse union
|
let queryM = matchUnion @QueryResponse union
|
||||||
let errorM = matchUnion @ErrorResponse union
|
let errorM = matchUnion @ErrorResponse union
|
||||||
case (queryM, errorM) of
|
let errorM400 = matchUnion @ErrorResponse400 union
|
||||||
(Just c, Nothing) -> queryAction c
|
case (queryM, errorM, errorM400) of
|
||||||
(Nothing, Just e) -> errorAction e
|
(Nothing, Nothing, Nothing) -> defaultAction
|
||||||
_ -> defaultAction -- Note, this could technically include the (Just _, Just _) scenario which is not possible.
|
(Just c, _, _) -> queryAction c
|
||||||
|
(_, Just e, _) -> errorAction e
|
||||||
|
(_, _, Just (WithStatus e)) -> errorAction e
|
||||||
|
|
||||||
type QueryResponses = '[V0.QueryResponse, V0.ErrorResponse]
|
type QueryResponses = '[V0.QueryResponse, V0.ErrorResponse, V0.ErrorResponse400]
|
||||||
|
|
||||||
type QueryApi =
|
type QueryApi =
|
||||||
"query"
|
"query"
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
module Hasura.Backends.DataConnector.API.V0.ErrorResponse
|
module Hasura.Backends.DataConnector.API.V0.ErrorResponse
|
||||||
( ErrorResponse (..),
|
( ErrorResponse (..),
|
||||||
|
ErrorResponse400,
|
||||||
ErrorResponseType (..),
|
ErrorResponseType (..),
|
||||||
errorResponseJsonText,
|
errorResponseJsonText,
|
||||||
errorResponseSummary,
|
errorResponseSummary,
|
||||||
@ -54,6 +55,8 @@ data ErrorResponse = ErrorResponse
|
|||||||
instance HasStatus ErrorResponse where
|
instance HasStatus ErrorResponse where
|
||||||
type StatusOf ErrorResponse = 500
|
type StatusOf ErrorResponse = 500
|
||||||
|
|
||||||
|
type ErrorResponse400 = Servant.WithStatus 400 ErrorResponse
|
||||||
|
|
||||||
{-# HLINT ignore "Use tshow" #-}
|
{-# HLINT ignore "Use tshow" #-}
|
||||||
errorResponseSummary :: ErrorResponse -> Text
|
errorResponseSummary :: ErrorResponse -> Text
|
||||||
errorResponseSummary ErrorResponse {..} = pack (show _crType) <> ": " <> _crMessage
|
errorResponseSummary ErrorResponse {..} = pack (show _crType) <> ": " <> _crMessage
|
||||||
|
@ -435,7 +435,7 @@ runGetTableInfo GetTableInfo {..} = do
|
|||||||
pure $ EncJSON.encJFromJValue table
|
pure $ EncJSON.encJFromJValue table
|
||||||
backend -> Error.throw500 ("Schema fetching is not supported for '" <> Text.E.toTxt backend <> "'")
|
backend -> Error.throw500 ("Schema fetching is not supported for '" <> Text.E.toTxt backend <> "'")
|
||||||
|
|
||||||
schemaGuard :: MonadError QErr m => Union '[API.SchemaResponse, API.ErrorResponse] -> m API.SchemaResponse
|
schemaGuard :: MonadError QErr m => Union API.SchemaResponses -> m API.SchemaResponse
|
||||||
schemaGuard = schemaCase defaultAction pure errorAction
|
schemaGuard = schemaCase defaultAction pure errorAction
|
||||||
where
|
where
|
||||||
defaultAction = throw400 DataConnectorError "Error resolving source schema"
|
defaultAction = throw400 DataConnectorError "Error resolving source schema"
|
||||||
|
Loading…
Reference in New Issue
Block a user