Skip to content

Commit

Permalink
Check for synthesized errors in ProperTrailers
Browse files Browse the repository at this point in the history
  • Loading branch information
edsko committed Jul 25, 2024
1 parent f4a264b commit 654e865
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 31 deletions.
4 changes: 2 additions & 2 deletions src/Network/GRPC/Client/Session.hs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ instance SupportsClientRpc rpc => InitiateSession (ClientSession rpc) where
parseResponse (ClientSession conn) (ResponseInfo status headers body) =
case classifyServerResponse (Proxy @rpc) status headers body of
Left parsed -> do
trailersOnly <- throwSynthesized parsed
trailersOnly <- throwSynthesized throwIO parsed
-- We classify the response as Trailers-Only if the grpc-status header
-- is present, or when the HTTP status is anything other than 200 OK
-- (which we treat, as per the spec, as an implicit grpc-status).
Expand All @@ -97,7 +97,7 @@ instance SupportsClientRpc rpc => InitiateSession (ClientSession rpc) where
Left err -> throwIO $ CallSetupInvalidResponseHeaders err
Right _hdrs -> return $ FlowStartNoMessages trailersOnly
Right parsed -> do
responseHeaders <- throwSynthesized parsed
responseHeaders <- throwSynthesized throwIO parsed
case verifyAllIf connVerifyHeaders responseHeaders of
Left err -> throwIO $ CallSetupInvalidResponseHeaders err
Right hdrs -> do
Expand Down
2 changes: 1 addition & 1 deletion src/Network/GRPC/Server/Call.hs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ determineInbound :: forall rpc.
-> HTTP2.Request
-> IO (Headers (ServerInbound rpc), Maybe Timeout)
determineInbound session req = do
requestHeaders' <- throwSynthesized parsed
requestHeaders' <- throwSynthesized throwIO parsed
case verifyAllIf serverVerifyHeaders requestHeaders' of
Left err -> throwIO $ CallSetupInvalidRequestHeaders err
Right hdrs -> do
Expand Down
12 changes: 6 additions & 6 deletions src/Network/GRPC/Spec/Headers/Invalid.hs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import Network.HTTP.Types qualified as HTTP
import Network.GRPC.Spec.Status
import Network.GRPC.Util.HKD (Checked)
import Network.GRPC.Util.HKD qualified as HKD
import Control.Exception

{-------------------------------------------------------------------------------
Definition
Expand Down Expand Up @@ -180,13 +179,14 @@ mapSynthesized :: (e -> e') -> InvalidHeaders e -> InvalidHeaders e'
mapSynthesized f = runIdentity . mapSynthesizedM (Identity . f)

throwSynthesized ::
HKD.Traversable h
=> h (Checked (InvalidHeaders GrpcException))
-> IO (h (Checked (InvalidHeaders HandledSynthesized)))
throwSynthesized =
(HKD.Traversable h, Monad m)
=> (forall a. GrpcException -> m a)
-> h (Checked (InvalidHeaders GrpcException))
-> m (h (Checked (InvalidHeaders HandledSynthesized)))
throwSynthesized throw =
HKD.traverse $
either
(fmap Left . mapSynthesizedM throwIO)
(fmap Left . mapSynthesizedM throw)
(fmap Right . return)

{-------------------------------------------------------------------------------
Expand Down
50 changes: 29 additions & 21 deletions src/Network/GRPC/Spec/Headers/Response.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module Network.GRPC.Spec.Headers.Response (
) where

import Control.Exception
import Control.Monad.Except (throwError)
import Data.List.NonEmpty (NonEmpty)
import Data.Proxy
import Data.Text (Text)
Expand Down Expand Up @@ -273,27 +274,34 @@ data GrpcNormalTermination = GrpcNormalTermination {
grpcClassifyTermination ::
ProperTrailers'
-> Either GrpcException GrpcNormalTermination
grpcClassifyTermination ProperTrailers {
properTrailersGrpcStatus
, properTrailersGrpcMessage
, properTrailersMetadata
} =
case properTrailersGrpcStatus of
Right GrpcOk -> Right GrpcNormalTermination {
grpcTerminatedMetadata = customMetadataMapToList properTrailersMetadata
}
Right (GrpcError err) -> Left GrpcException{
grpcError = err
, grpcErrorMessage = case properTrailersGrpcMessage of
Right msg -> msg
Left _ -> Just "Invalid grpc-message"
, grpcErrorMetadata = customMetadataMapToList properTrailersMetadata
}
Left _invalidStatus -> Left GrpcException {
grpcError = GrpcUnknown
, grpcErrorMessage = Just "Invalid grpc-status"
, grpcErrorMetadata = customMetadataMapToList properTrailersMetadata
}
grpcClassifyTermination =
-- If there are any synthesized errors, those take precedence
either Left aux . throwSynthesized throwError
where
aux ::
ProperTrailers_ (Checked (InvalidHeaders HandledSynthesized))
-> Either GrpcException GrpcNormalTermination
aux ProperTrailers { properTrailersGrpcStatus
, properTrailersGrpcMessage
, properTrailersMetadata
} =
case properTrailersGrpcStatus of
Right GrpcOk -> Right GrpcNormalTermination {
grpcTerminatedMetadata =
customMetadataMapToList properTrailersMetadata
}
Right (GrpcError err) -> Left GrpcException{
grpcError = err
, grpcErrorMessage = case properTrailersGrpcMessage of
Right msg -> msg
Left _ -> Just "Invalid grpc-message"
, grpcErrorMetadata = customMetadataMapToList properTrailersMetadata
}
Left _invalidStatus -> Left GrpcException {
grpcError = GrpcUnknown
, grpcErrorMessage = Just "Invalid grpc-status"
, grpcErrorMetadata = customMetadataMapToList properTrailersMetadata
}

-- | Translate gRPC exception to response trailers
grpcExceptionToTrailers :: GrpcException -> ProperTrailers
Expand Down
2 changes: 1 addition & 1 deletion test-grapesy/Test/Driver/ClientServer.hs
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ withTestServer cfg firstTestFailure handlerLock serverHandlers k = do
Nothing -> Server.ServerConfig {
serverInsecure = Just Server.InsecureConfig {
insecureHost = Just "127.0.0.1"
, insecurePort = 50051 -- serverPort cfg
, insecurePort = serverPort cfg
}
, serverSecure = Nothing
}
Expand Down

0 comments on commit 654e865

Please sign in to comment.