diff --git a/src/Network/GRPC/Client/Session.hs b/src/Network/GRPC/Client/Session.hs index 53acf715..2ba037d0 100644 --- a/src/Network/GRPC/Client/Session.hs +++ b/src/Network/GRPC/Client/Session.hs @@ -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). @@ -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 diff --git a/src/Network/GRPC/Server/Call.hs b/src/Network/GRPC/Server/Call.hs index ceb4cdfa..bbbdbbfc 100644 --- a/src/Network/GRPC/Server/Call.hs +++ b/src/Network/GRPC/Server/Call.hs @@ -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 diff --git a/src/Network/GRPC/Spec/Headers/Invalid.hs b/src/Network/GRPC/Spec/Headers/Invalid.hs index 9089b889..7c16f861 100644 --- a/src/Network/GRPC/Spec/Headers/Invalid.hs +++ b/src/Network/GRPC/Spec/Headers/Invalid.hs @@ -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 @@ -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) {------------------------------------------------------------------------------- diff --git a/src/Network/GRPC/Spec/Headers/Response.hs b/src/Network/GRPC/Spec/Headers/Response.hs index 1a19d5bc..45c32ac1 100644 --- a/src/Network/GRPC/Spec/Headers/Response.hs +++ b/src/Network/GRPC/Spec/Headers/Response.hs @@ -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) @@ -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 diff --git a/test-grapesy/Test/Driver/ClientServer.hs b/test-grapesy/Test/Driver/ClientServer.hs index a0eb118d..d9d70bb4 100644 --- a/test-grapesy/Test/Driver/ClientServer.hs +++ b/test-grapesy/Test/Driver/ClientServer.hs @@ -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 }