server: improve event trigger logging

https://github.com/hasura/graphql-engine-mono/pull/2286

GitOrigin-RevId: b3232a08dd7ec2aa0c9e7a2fada0e05e34a1897b
This commit is contained in:
Karthikeyan Chinnakonda 2021-09-20 18:44:28 +05:30 committed by hasura-bot
parent d358d06e68
commit ccf97ab6b0
12 changed files with 172 additions and 100 deletions

View File

@ -3,6 +3,12 @@
## Next release
(Add entries below in the order of server, console, cli, docs, others)
- server: improve the event trigger logging on errors
NOTE: This change introduces a breaking change, earlier when there
was a client error when trying to process an event, then the status was reported as 1000. Now, the status 1000 has been removed and if any status was received by the graphql-engine from the webhook, the status
of the invocation will be the same otherwise it will be `NULL`.
- server: support `extensions` field in error responses from action webhook endpoints (fix #4001)
- server: fix custom-check based permissions for MSSQL (#7429)
- server: remove identity notion for table columns (fix #7557)
- server: add webhook transformations for Actions and EventTriggers
@ -15,8 +21,6 @@
- server: prevent empty subscription roots in the schema (#6898)
- console: support tracking of functions with return a single row
- server: support `extensions` field in error responses from action webhook endpoints (fix #4001)
## v2.0.9
- server: fix export_metadata V2 bug which included cron triggers with `include_in_metadata: false`

View File

@ -227,7 +227,7 @@ insertInvocation invo = do
INSERT INTO hdb_catalog.event_invocation_logs (event_id, status, request, response)
VALUES ($1, $2, $3, $4)
|] ( iEventId invo
, fromIntegral $ iStatus invo :: Int64
, fromIntegral <$> iStatus invo :: Maybe Int64
, Q.AltJ $ toJSON $ iRequest invo
, Q.AltJ $ toJSON $ iResponse invo) True
Q.unitQE defaultTxErrorHandler [Q.sql|

View File

@ -79,6 +79,7 @@ import Hasura.Backends.Postgres.SQL.Types hiding (TableName)
import Hasura.Base.Error
import Hasura.Eventing.Common
import Hasura.Eventing.HTTP
import Hasura.HTTP (getHTTPExceptionStatus)
import Hasura.RQL.DDL.Headers
import Hasura.RQL.DDL.RequestTransform
import Hasura.RQL.Types
@ -372,7 +373,7 @@ processEventQueue logger logBehavior httpMgr getSchemaCache EventEngineCtx{..} L
runExceptT (setRetry sourceConfig e (addUTCTime 60 currentTime) maintenanceModeVersion) >>=
flip onLeft logQErr
Right eti -> runTraceT (spanName eti) do
let webhookUrl = T.unpack $ wciCachedValue $ etiWebhookInfo eti
let webhook = wciCachedValue $ etiWebhookInfo eti
retryConf = etiRetryConf eti
timeoutSeconds = fromMaybe defaultTimeoutSeconds (rcTimeoutSec retryConf)
httpTimeout = HTTP.responseTimeoutMicro (timeoutSeconds * 1000000)
@ -385,7 +386,7 @@ processEventQueue logger logBehavior httpMgr getSchemaCache EventEngineCtx{..} L
res <- runExceptT $ do
-- reqDetails contains the pre and post transformation
-- request for logging purposes.
reqDetails <- mkRequest headers httpTimeout payload dataTransform webhookUrl
reqDetails <- mkRequest headers httpTimeout payload dataTransform webhook
let logger' res details = logHTTPForET res extraLogCtx details logBehavior
-- Event Triggers have a configuration parameter called
-- HASURA_GRAPHQL_EVENTS_HTTP_WORKERS, which is used
@ -432,7 +433,7 @@ processSuccess sourceConfig e reqHeaders ep maintenanceModeVersion resp = do
let respBody = hrsBody resp
respHeaders = hrsHeaders resp
respStatus = hrsStatus resp
invocation = mkInvocation ep respStatus reqHeaders respBody respHeaders
invocation = mkInvocation ep (Just respStatus) reqHeaders respBody respHeaders
recordSuccess @b sourceConfig e invocation maintenanceModeVersion
processError
@ -450,20 +451,17 @@ processError
-> m (Either QErr ())
processError sourceConfig e retryConf reqHeaders ep maintenanceModeVersion err = do
let invocation = case err of
HClient excp -> do
let errMsg = TBS.fromLBS $ encode $ show excp
mkInvocation ep 1000 reqHeaders errMsg []
HParse _ detail -> do
let errMsg = TBS.fromLBS $ encode detail
mkInvocation ep 1001 reqHeaders errMsg []
HClient httpException ->
let statusMaybe = getHTTPExceptionStatus httpException
in mkInvocation ep statusMaybe reqHeaders (TBS.fromLBS (encode httpException)) []
HStatus errResp -> do
let respPayload = hrsBody errResp
respHeaders = hrsHeaders errResp
respStatus = hrsStatus errResp
mkInvocation ep respStatus reqHeaders respPayload respHeaders
mkInvocation ep (Just respStatus) reqHeaders respPayload respHeaders
HOther detail -> do
let errMsg = TBS.fromLBS $ encode detail
mkInvocation ep 500 reqHeaders errMsg []
mkInvocation ep (Just 500) reqHeaders errMsg []
retryOrError <- retryOrSetError e retryConf err
recordError @b sourceConfig e invocation retryOrError maintenanceModeVersion
@ -497,21 +495,25 @@ retryOrSetError e retryConf err = do
mkInvocation
:: Backend b
=> EventPayload b
-> Int
-> Maybe Int
-> [HeaderConf]
-> TBS.TByteString
-> [HeaderConf]
-> Invocation 'EventType
mkInvocation ep status reqHeaders respBody respHeaders
= let resp = if isClientError status
then mkClientErr respBody
else mkResp status respBody respHeaders
in
Invocation
(epId ep)
status
(mkWebhookReq (toJSON ep) reqHeaders invocationVersionET)
resp
mkInvocation eventPayload statusMaybe reqHeaders respBody respHeaders =
let resp =
case statusMaybe of
Nothing -> mkClientErr respBody
Just status ->
if status >= 200 && status < 300
then mkResp status respBody respHeaders
else mkClientErr respBody
in
Invocation
(epId eventPayload)
statusMaybe
(mkWebhookReq (toJSON eventPayload) reqHeaders invocationVersionET)
resp
logQErr :: ( MonadReader r m, Has (L.Logger L.Hasura) r, MonadIO m) => QErr -> m ()
logQErr err = do

View File

@ -27,6 +27,7 @@ module Hasura.Eventing.HTTP
, mkClientErr
, mkWebhookReq
, mkResp
, mkInvocationResp
, LogBehavior(..)
, ResponseLogBehavior(..)
, HeaderLogBehavior(..)
@ -57,11 +58,12 @@ import Data.Aeson.TH
import Data.Either
import Data.Has
import Data.Int (Int64)
import Hasura.HTTP (addDefaultHeaders)
import Hasura.HTTP (HttpException (..), addDefaultHeaders)
import Hasura.Logging
import Hasura.Prelude
import Hasura.RQL.DDL.Headers
import Hasura.RQL.DDL.RequestTransform (RequestTransform, applyRequestTransform)
import Hasura.RQL.Types.Common (ResolvedWebhook (..))
import Hasura.RQL.Types.EventTrigger
import Hasura.RQL.Types.Eventing
import Hasura.Server.Version (HasVersion)
@ -95,7 +97,6 @@ data HTTPResp (a :: TriggerTypes)
, hrsBody :: !TBS.TByteString
, hrsSize :: !Int64
} deriving (Show, Eq)
$(deriveToJSON hasuraJSON{omitNothingFields=True} ''HTTPResp)
instance ToEngineLog (HTTPResp 'EventType) Hasura where
@ -105,22 +106,18 @@ instance ToEngineLog (HTTPResp 'ScheduledType) Hasura where
toEngineLog resp = (LevelInfo, scheduledTriggerLogType, toJSON resp)
data HTTPErr (a :: TriggerTypes)
= HClient !HTTP.HttpException
| HParse !HTTP.Status !String
= HClient !HttpException
| HStatus !(HTTPResp a)
| HOther !String
deriving (Show)
instance ToJSON (HTTPErr a) where
toJSON err = toObj $ case err of
(HClient e) -> ("client", toJSON $ show e)
(HParse st e) ->
( "parse"
, toJSON (HTTP.statusCode st, show e)
)
(HClient httpException) ->
("client", toJSON httpException)
(HStatus resp) ->
("status", toJSON resp)
(HOther e) -> ("internal", toJSON $ show e)
(HOther e) -> ("internal", toJSON e)
where
toObj :: (Text, Value) -> Value
toObj (k, v) = object [ "type" .= k
@ -200,12 +197,13 @@ isNetworkError = \case
HClient he -> isNetworkErrorHC he
_ -> False
isNetworkErrorHC :: HTTP.HttpException -> Bool
isNetworkErrorHC = \case
HTTP.HttpExceptionRequest _ (HTTP.ConnectionFailure _) -> True
HTTP.HttpExceptionRequest _ HTTP.ConnectionTimeout -> True
HTTP.HttpExceptionRequest _ HTTP.ResponseTimeout -> True
_ -> False
isNetworkErrorHC :: HttpException -> Bool
isNetworkErrorHC (HttpException exception) =
case exception of
HTTP.HttpExceptionRequest _ (HTTP.ConnectionFailure _) -> True
HTTP.HttpExceptionRequest _ HTTP.ConnectionTimeout -> True
HTTP.HttpExceptionRequest _ HTTP.ResponseTimeout -> True
_ -> False
anyBodyParser :: HTTP.Response LBS.ByteString -> Either (HTTPErr a) (HTTPResp a)
anyBodyParser resp = do
@ -261,7 +259,7 @@ logHTTPForST eitherResp extraLogCtx reqDetails logBehavior = do
runHTTP :: (MonadIO m) => HTTP.Manager -> HTTP.Request -> m (Either (HTTPErr a) (HTTPResp a))
runHTTP manager req = do
res <- liftIO $ try $ HTTP.performRequest req manager
return $ either (Left . HClient) anyBodyParser res
return $ either (Left . HClient . HttpException) anyBodyParser res
mkRequest ::
MonadError (HTTPErr a) m
@ -272,11 +270,11 @@ mkRequest ::
-- log the request size. As the logging happens outside the function, we pass
-- it the final request body, instead of 'Value'
-> Maybe RequestTransform
-> String
-> ResolvedWebhook
-> m RequestDetails
mkRequest headers timeout payload mRequestTransform webhook =
case HTTP.mkRequestEither (T.pack webhook) of
Left excp -> throwError $ HClient excp
mkRequest headers timeout payload mRequestTransform (ResolvedWebhook webhook) =
case HTTP.mkRequestEither webhook of
Left excp -> throwError $ HClient $ HttpException excp
Right initReq ->
let req = initReq & set HTTP.method "POST"
& set HTTP.headers headers
@ -319,8 +317,17 @@ mkClientErr message =
mkWebhookReq :: Value -> [HeaderConf] -> InvocationVersion -> WebhookRequest
mkWebhookReq payload headers = WebhookRequest payload headers
mkInvocationResp :: Maybe Int -> TBS.TByteString -> [HeaderConf] -> Response a
mkInvocationResp statusMaybe responseBody responseHeaders =
case statusMaybe of
Nothing -> mkClientErr responseBody
Just status ->
if isClientError status
then mkClientErr responseBody
else mkResp status responseBody responseHeaders
isClientError :: Int -> Bool
isClientError status = status >= 1000
isClientError status = status >= 300
encodeHeader :: EventHeaderInfo -> HTTP.Header
encodeHeader (EventHeaderInfo hconf cache) =

View File

@ -117,7 +117,6 @@ import qualified Data.HashMap.Strict as Map
import qualified Data.List.NonEmpty as NE
import qualified Data.Set as Set
import qualified Data.TByteString as TBS
import qualified Data.Text as T
import qualified Database.PG.Query as Q
import qualified Network.HTTP.Client.Transformable as HTTP
import qualified Text.Builder as TB
@ -140,6 +139,7 @@ import Hasura.Base.Error
import Hasura.Eventing.Common
import Hasura.Eventing.HTTP
import Hasura.Eventing.ScheduledTrigger.Types
import Hasura.HTTP (getHTTPExceptionStatus)
import Hasura.Metadata.Class
import Hasura.RQL.DDL.EventTrigger (getHeaderInfosFromConf)
import Hasura.RQL.DDL.Headers
@ -147,7 +147,6 @@ import Hasura.RQL.Types
import Hasura.SQL.Types
import Hasura.Server.Version (HasVersion)
-- | runCronEventsGenerator makes sure that all the cron triggers
-- have an adequate buffer of cron events.
runCronEventsGenerator
@ -240,14 +239,13 @@ processCronEvents logger logBehavior httpMgr cronEvents getSC lockedCronEvents =
Nothing -> logInternalError $
err500 Unexpected "could not find cron trigger in cache"
Just CronTriggerInfo{..} -> do
let webhookUrl = unResolvedWebhook ctiWebhookInfo
payload = ScheduledEventWebhookPayload id' (Just name) st
let payload = ScheduledEventWebhookPayload id' (Just name) st
(fromMaybe J.Null ctiPayload) ctiComment
Nothing
retryCtx = RetryContext tries ctiRetryConf
finally <- runMetadataStorageT $ flip runReaderT (logger, httpMgr) $
processScheduledEvent logBehavior id' ctiHeaders retryCtx
payload webhookUrl Cron
payload ctiWebhookInfo Cron
removeEventFromLockedEvents id' lockedCronEvents
onLeft finally logInternalError
where
@ -276,14 +274,13 @@ processOneOffScheduledEvents env logger logBehavior httpMgr
(either logInternalError pure) =<< runMetadataStorageT do
webhookInfo <- resolveWebhook env _ooseWebhookConf
headerInfo <- getHeaderInfosFromConf env _ooseHeaderConf
let webhookUrl = unResolvedWebhook webhookInfo
payload = ScheduledEventWebhookPayload _ooseId Nothing
let payload = ScheduledEventWebhookPayload _ooseId Nothing
_ooseScheduledTime (fromMaybe J.Null _oosePayload)
_ooseComment (Just _ooseCreatedAt)
retryCtx = RetryContext _ooseTries _ooseRetryConf
flip runReaderT (logger, httpMgr) $
processScheduledEvent logBehavior _ooseId headerInfo retryCtx payload webhookUrl OneOff
processScheduledEvent logBehavior _ooseId headerInfo retryCtx payload webhookInfo OneOff
removeEventFromLockedEvents _ooseId lockedOneOffScheduledEvents
where
logInternalError err = liftIO . L.unLogger logger $ ScheduledTriggerInternalErr err
@ -331,7 +328,7 @@ processScheduledEvent
-> [EventHeaderInfo]
-> RetryContext
-> ScheduledEventWebhookPayload
-> Text
-> ResolvedWebhook
-> ScheduledEventType
-> m ()
processScheduledEvent logBehavior eventId eventHeaders retryCtx payload webhookUrl type'
@ -350,11 +347,10 @@ processScheduledEvent logBehavior eventId eventHeaders retryCtx payload webhookU
extraLogCtx = ExtraLogContext eventId (sewpName payload)
webhookReqBodyJson = J.toJSON payload
webhookReqBody = J.encode webhookReqBodyJson
eitherRes <- runExceptT $ do
-- reqDetails contains the pre and post transformation
-- request for logging purposes.
reqDetails <- mkRequest headers httpTimeout webhookReqBody Nothing (T.unpack webhookUrl)
reqDetails <- mkRequest headers httpTimeout webhookReqBody Nothing webhookUrl
let logger e d = logHTTPForST e extraLogCtx d logBehavior
hoistEither =<< lift (invokeRequest reqDetails logger)
case eitherRes of
@ -376,20 +372,17 @@ processError
-> m ()
processError eventId retryCtx decodedHeaders type' reqJson err = do
let invocation = case err of
HClient excp -> do
let errMsg = TBS.fromLBS $ J.encode $ show excp
mkInvocation eventId 1000 decodedHeaders errMsg [] reqJson
HParse _ detail -> do
let errMsg = TBS.fromLBS $ J.encode detail
mkInvocation eventId 1001 decodedHeaders errMsg [] reqJson
HClient httpException ->
let statusMaybe = getHTTPExceptionStatus httpException
in mkInvocation eventId statusMaybe decodedHeaders (TBS.fromLBS $ J.encode httpException) [] reqJson
HStatus errResp -> do
let respPayload = hrsBody errResp
respHeaders = hrsHeaders errResp
respStatus = hrsStatus errResp
mkInvocation eventId respStatus decodedHeaders respPayload respHeaders reqJson
mkInvocation eventId (Just respStatus) decodedHeaders respPayload respHeaders reqJson
HOther detail -> do
let errMsg = (TBS.fromLBS $ J.encode detail)
mkInvocation eventId 500 decodedHeaders errMsg [] reqJson
mkInvocation eventId (Just 500) decodedHeaders errMsg [] reqJson
insertScheduledEventInvocation invocation type'
retryOrMarkError eventId retryCtx err type'
@ -461,7 +454,7 @@ processSuccess eventId decodedHeaders type' reqBodyJson resp = do
let respBody = hrsBody resp
respHeaders = hrsHeaders resp
respStatus = hrsStatus resp
invocation = mkInvocation eventId respStatus decodedHeaders respBody respHeaders reqBodyJson
invocation = mkInvocation eventId (Just respStatus) decodedHeaders respBody respHeaders reqBodyJson
insertScheduledEventInvocation invocation type'
setScheduledEventOp eventId (SEOpStatus SESDelivered) type'
@ -473,22 +466,18 @@ processDead eventId type' =
mkInvocation
:: ScheduledEventId
-> Int
-> Maybe Int
-> [HeaderConf]
-> TBS.TByteString
-> [HeaderConf]
-> J.Value
-> (Invocation 'ScheduledType)
mkInvocation eventId status reqHeaders respBody respHeaders reqBodyJson
= let resp = if isClientError status
then mkClientErr respBody
else mkResp status respBody respHeaders
in
Invocation
eventId
status
(mkWebhookReq reqBodyJson reqHeaders invocationVersionST)
resp
mkInvocation eventId status reqHeaders respBody respHeaders reqBodyJson =
Invocation
eventId
status
(mkWebhookReq reqBodyJson reqHeaders invocationVersionST)
(mkInvocationResp status respBody respHeaders)
-- metadata database transactions
@ -580,7 +569,7 @@ insertInvocationTx invo type' = do
(event_id, status, request, response)
VALUES ($1, $2, $3, $4)
|] ( iEventId invo
, fromIntegral $ iStatus invo :: Int64
, fromIntegral <$> iStatus invo :: Maybe Int64
, Q.AltJ $ J.toJSON $ iRequest invo
, Q.AltJ $ J.toJSON $ iResponse invo) True
Q.unitQE defaultTxErrorHandler [Q.sql|
@ -595,7 +584,7 @@ insertInvocationTx invo type' = do
(event_id, status, request, response)
VALUES ($1, $2, $3, $4)
|] ( iEventId invo
, fromIntegral $ iStatus invo :: Int64
, fromIntegral <$> iStatus invo :: Maybe Int64
, Q.AltJ $ J.toJSON $ iRequest invo
, Q.AltJ $ J.toJSON $ iResponse invo) True
Q.unitQE defaultTxErrorHandler [Q.sql|

View File

@ -5,6 +5,8 @@ module Hasura.HTTP
, addDefaultHeaders
, HttpResponse(..)
, addHttpResponseHeaders
, getHTTPExceptionStatus
, serializeHTTPExceptionMessage
) where
import Hasura.Prelude
@ -14,10 +16,14 @@ import Data.CaseInsensitive (original)
import Data.Text.Conversions (UTF8 (..), convertText)
import qualified Data.Aeson as J
import qualified Data.HashMap.Strict as M
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Network.HTTP.Client as HTTP
import qualified Network.HTTP.Types as HTTP
import qualified Network.Wreq as Wreq
import Hasura.Server.Utils (redactSensitiveHeader)
import Hasura.Server.Version (HasVersion, currentVersion)
hdrsToText :: [HTTP.Header] -> [(Text, Text)]
@ -55,16 +61,68 @@ newtype HttpException
{ unHttpException :: HTTP.HttpException }
deriving (Show)
getHTTPExceptionStatus :: HttpException -> Maybe Int
getHTTPExceptionStatus = \case
(HttpException (HTTP.HttpExceptionRequest _ httpExceptionContent)) ->
case httpExceptionContent of
HTTP.StatusCodeException response _ -> Just $ HTTP.statusCode $ HTTP.responseStatus response
HTTP.ProxyConnectException _ _ status -> Just $ HTTP.statusCode status
_ -> Nothing
(HttpException (HTTP.InvalidUrlException _ _)) -> Nothing
serializeHTTPExceptionMessage :: HttpException -> Text
serializeHTTPExceptionMessage (HttpException (HTTP.HttpExceptionRequest _ httpExceptionContent)) =
case httpExceptionContent of
HTTP.StatusCodeException _ _ -> "unexpected"
HTTP.TooManyRedirects _ -> "Too many redirects"
HTTP.OverlongHeaders -> "Overlong headers"
HTTP.ResponseTimeout -> "Response timeout"
HTTP.ConnectionTimeout -> "Connection timeout"
HTTP.ConnectionFailure _ -> "Connection failure"
HTTP.InvalidStatusLine _ -> "Invalid HTTP Status Line"
HTTP.InternalException _ -> "Internal Exception"
HTTP.ProxyConnectException _ _ _ -> "Proxy connection exception"
HTTP.NoResponseDataReceived -> "No response data received"
HTTP.TlsNotSupported -> "TLS not supported"
HTTP.InvalidDestinationHost _ -> "Invalid destination host"
HTTP.InvalidHeader _ -> "Invalid Header"
HTTP.InvalidRequestHeader _ -> "Invalid Request Header"
HTTP.WrongRequestBodyStreamSize _ _ -> "Wrong request body stream size"
HTTP.ResponseBodyTooShort _ _ -> "Response body too short"
HTTP.InvalidChunkHeaders -> "Invalid chunk headers"
HTTP.IncompleteHeaders -> "Incomplete headers"
_ -> "unexpected"
serializeHTTPExceptionMessage (HttpException (HTTP.InvalidUrlException url reason)) = T.pack $ "URL: " <> url <> " is invalid because " <> reason
encodeHTTPRequestJSON :: HTTP.Request -> J.Value
encodeHTTPRequestJSON request =
J.Object $ M.fromList
[ ("host", J.toJSON $ TE.decodeUtf8 $ HTTP.host request)
, ("port" , J.toJSON $ HTTP.port request)
, ("secure", J.toJSON $ HTTP.secure request)
, ("requestHeaders" , J.toJSON $ M.fromList $ hdrsToText $ map redactSensitiveHeader $ HTTP.requestHeaders request)
, ("path" , J.toJSON $ TE.decodeUtf8 $ HTTP.path request)
, ("queryString", J.toJSON $ TE.decodeUtf8 $ HTTP.queryString request)
, ("method", J.toJSON $ TE.decodeUtf8 $ HTTP.method request)
, ("responseTimeout", J.String $ tshow $ HTTP.responseTimeout request)
]
instance J.ToJSON HttpException where
toJSON = \case
(HttpException (HTTP.InvalidUrlException _ e)) ->
J.object [ "type" J..= ("invalid_url" :: Text)
, "message" J..= e
]
(HttpException (HTTP.HttpExceptionRequest _ cont)) ->
J.object [ "type" J..= ("http_exception" :: Text)
, "message" J..= show cont
]
toJSON httpException =
case httpException of
(HttpException (HTTP.InvalidUrlException _ e)) ->
J.object [ "type" J..= ("invalid_url" :: Text)
, "message" J..= e
]
(HttpException (HTTP.HttpExceptionRequest req _)) ->
let statusMaybe = getHTTPExceptionStatus httpException
exceptionContent = serializeHTTPExceptionMessage httpException
reqJSON = encodeHTTPRequestJSON req
in
J.object $ [ "type" J..= ("http_exception" :: Text)
, "message" J..= exceptionContent
, "request" J..= reqJSON
] <> maybe mempty (\status -> [ "status" J..= status]) statusMaybe
data HttpResponse a
= HttpResponse

View File

@ -302,13 +302,13 @@ getWebhookInfoFromConf
=> Env.Environment
-> WebhookConf
-> m WebhookConfInfo
getWebhookInfoFromConf env wc = case wc of
getWebhookInfoFromConf env webhookConf = case webhookConf of
WCValue w -> do
resolvedWebhook <- resolveWebhook env w
return $ WebhookConfInfo wc $ unResolvedWebhook resolvedWebhook
WCEnv we -> do
envVal <- getEnv env we
return $ WebhookConfInfo wc envVal
return $ WebhookConfInfo webhookConf resolvedWebhook
WCEnv webhookEnvVar -> do
envVal <- getEnv env webhookEnvVar
return $ WebhookConfInfo webhookConf (ResolvedWebhook envVal)
buildEventTriggerInfo
:: forall b m

View File

@ -254,8 +254,10 @@ instance FromJSON NonNegativeDiffTime where
False -> fail "negative value not allowed"
newtype ResolvedWebhook
= ResolvedWebhook { unResolvedWebhook :: Text }
deriving ( Show, Eq, FromJSON, ToJSON, Hashable, ToTxt)
= ResolvedWebhook { unResolvedWebhook :: Text}
deriving ( Show, Eq, FromJSON, ToJSON, Hashable, ToTxt, Generic)
instance NFData ResolvedWebhook
instance Cacheable ResolvedWebhook
newtype InputWebhook
= InputWebhook {unInputWebhook :: URLTemplate}

View File

@ -43,7 +43,7 @@ import Hasura.Incremental (Cacheable)
import Hasura.RQL.DDL.Headers
import Hasura.RQL.DDL.RequestTransform (MetadataTransform)
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Common (InputWebhook, SourceName)
import Hasura.RQL.Types.Common (InputWebhook, ResolvedWebhook, SourceName)
import Hasura.RQL.Types.Eventing
import Hasura.SQL.Backend
@ -143,9 +143,10 @@ instance FromJSON WebhookConf where
data WebhookConfInfo
= WebhookConfInfo
{ wciWebhookConf :: !WebhookConf
, wciCachedValue :: !Text
, wciCachedValue :: !ResolvedWebhook
} deriving (Show, Eq, Generic)
instance NFData WebhookConfInfo
instance Cacheable WebhookConfInfo
$(deriveToJSON hasuraJSON{omitNothingFields=True} ''WebhookConfInfo)
-- | The table operations on which the event trigger will be invoked.

View File

@ -81,7 +81,7 @@ instance ToJSON (Response 'ScheduledType) where
data Invocation (a :: TriggerTypes)
= Invocation
{ iEventId :: EventId
, iStatus :: Int
, iStatus :: Maybe Int
, iRequest :: WebhookRequest
, iResponse :: Response a
}

View File

@ -307,3 +307,12 @@ deprecatedEnvVars = DeprecatedEnvVars
, "HASURA_GRAPHQL_QUERY_PLAN_CACHE_SIZE"
, "HASURA_GRAPHQL_STRIPES_PER_READ_REPLICA"
]
sensitiveHeaders :: HashSet HTTP.HeaderName
sensitiveHeaders = Set.fromList
[ "Authorization"
, "Cookie"
]
redactSensitiveHeader :: HTTP.Header -> HTTP.Header
redactSensitiveHeader (headerName, value) = (headerName, if headerName `elem` sensitiveHeaders then "<REDACTED>" else value)

View File

@ -664,4 +664,4 @@ class TestActionTimeout:
time.sleep(4)
response, _ = check_query(hge_ctx, conf)
assert 'errors' in response['data']['create_user']
assert 'ResponseTimeout' == response['data']['create_user']['errors']['internal']['error']['message']
assert 'Response timeout' == response['data']['create_user']['errors']['internal']['error']['message']