-- | Construct HTTP2 requests
--
-- Intended for qualified import.
--
-- > import Network.GRPC.Spec.Request qualified as Req
module Network.GRPC.Spec.Headers.Request (
    -- * Inputs (message sent to the peer)
    RequestHeaders_(..)
  , RequestHeaders
  , RequestHeaders'
  ) where

import Data.ByteString qualified as Strict (ByteString)
import Data.List.NonEmpty (NonEmpty)
import GHC.Generics (Generic)

import Network.GRPC.Spec.Compression (CompressionId)
import Network.GRPC.Spec.CustomMetadata.Map
import Network.GRPC.Spec.Headers.Common
import Network.GRPC.Spec.Headers.Invalid
import Network.GRPC.Spec.Timeout
import Network.GRPC.Spec.TraceContext
import Network.GRPC.Spec.Util.HKD (HKD, Undecorated, Checked)
import Network.GRPC.Spec.Util.HKD qualified as HKD

{-------------------------------------------------------------------------------
  Inputs (message sent to the peer)
-------------------------------------------------------------------------------}

-- | Full set of call parameters required to construct the RPC call
--
-- This is constructed internally; it is not part of the public API.
data RequestHeaders_ f = RequestHeaders {
      -- | Timeout
      forall (f :: * -> *). RequestHeaders_ f -> HKD f (Maybe Timeout)
requestTimeout :: HKD f (Maybe Timeout)

      -- | Compression used for outgoing messages
    , forall (f :: * -> *).
RequestHeaders_ f -> HKD f (Maybe CompressionId)
requestCompression :: HKD f (Maybe CompressionId)

      -- | Accepted compression algorithms for incoming messages
      --
      -- @Maybe (NonEmpty ..)@ is perhaps a bit strange (why not just @[]@), but
      -- it emphasizes the specification: /if/ the header is present, it must be
      -- a non-empty list.
    , forall (f :: * -> *).
RequestHeaders_ f -> HKD f (Maybe (NonEmpty CompressionId))
requestAcceptCompression :: HKD f (Maybe (NonEmpty CompressionId))

      -- | Optionally, override the content-type
      --
      -- Set to 'Nothing' to omit the content-type header altogether.
      --
      -- See also discussion of 'requestMessageType'.
    , forall (f :: * -> *).
RequestHeaders_ f -> HKD f (Maybe ContentType)
requestContentType :: HKD f (Maybe ContentType)

      -- | Should we include the @Message-Type@ header?
      --
      -- Set to 'Nothing' to omit the message-type header altogether.
      --
      -- We do not need the header in order to know the message type, because
      -- the /path/ determines the service and method, and that in turn
      -- determines the message type. If it /is/ present, however, we verify
      -- that it has the valeu we expect.
    , forall (f :: * -> *).
RequestHeaders_ f -> HKD f (Maybe MessageType)
requestMessageType :: HKD f (Maybe MessageType)

      -- | User agent
    , forall (f :: * -> *). RequestHeaders_ f -> HKD f (Maybe ByteString)
requestUserAgent :: HKD f (Maybe Strict.ByteString)

      -- | Should we include the @te: trailers@ header?
      --
      -- The @TE@ header is part of the HTTP specification;
      -- see also <https://datatracker.ietf.org/doc/html/rfc7230#section-4.3>.
      -- It indicates that we are willing to accept a chunked encoding for the
      -- response body, and that we expect trailers to be present after the
      -- response body.
      --
      -- To be conform to the gRPC spec, the @te@ header should be included, but
      -- we does not insist that the header is present for incoming requests.
      -- However, /if/ it is present, we /do/ verify that it has the right
      -- value; this prevents values getting lost without notice.
    , forall (f :: * -> *). RequestHeaders_ f -> HKD f Bool
requestIncludeTE :: HKD f Bool

      -- | Trace context (for OpenTelemetry)
    , forall (f :: * -> *).
RequestHeaders_ f -> HKD f (Maybe TraceContext)
requestTraceContext :: HKD f (Maybe TraceContext)

      -- | Previous RPC attempts
      --
      -- This is part of automatic retries.
      -- See <https://github.com/grpc/proposal/blob/master/A6-client-retries.md>.
    , forall (f :: * -> *). RequestHeaders_ f -> HKD f (Maybe Int)
requestPreviousRpcAttempts :: HKD f (Maybe Int)

      -- | Custom metadata
      --
      -- Any header we do not otherwise explicitly support we attempt to parse
      -- as custom metadata. Headers for which this fails end up in
      -- 'requestUnrecognized'; reasons for this include the use of reserved
      -- header names (starting with @grpc-@), invalid binary encodings, etc.
    , forall (f :: * -> *). RequestHeaders_ f -> CustomMetadataMap
requestMetadata :: CustomMetadataMap

      -- | Unrecognized headers
    , forall (f :: * -> *). RequestHeaders_ f -> HKD f ()
requestUnrecognized :: HKD f ()
    }
  deriving anyclass (RequestHeaders_ (DecoratedWith Identity)
-> RequestHeaders_ Undecorated
RequestHeaders_ Undecorated
-> RequestHeaders_ (DecoratedWith Identity)
(RequestHeaders_ (DecoratedWith Identity)
 -> RequestHeaders_ Undecorated)
-> (RequestHeaders_ Undecorated
    -> RequestHeaders_ (DecoratedWith Identity))
-> Coerce RequestHeaders_
forall (t :: (* -> *) -> *).
(t (DecoratedWith Identity) -> t Undecorated)
-> (t Undecorated -> t (DecoratedWith Identity)) -> Coerce t
$cundecorate :: RequestHeaders_ (DecoratedWith Identity)
-> RequestHeaders_ Undecorated
undecorate :: RequestHeaders_ (DecoratedWith Identity)
-> RequestHeaders_ Undecorated
$cdecorate :: RequestHeaders_ Undecorated
-> RequestHeaders_ (DecoratedWith Identity)
decorate :: RequestHeaders_ Undecorated
-> RequestHeaders_ (DecoratedWith Identity)
HKD.Coerce)

-- | Request headers (without allowing for invalid headers)
--
-- NOTE: The HKD type
--
-- > RequestHeaders_ Undecorated
--
-- means that each field of type @HKD f a@ is simply of type @a@ (that is,
-- undecorated).
type RequestHeaders = RequestHeaders_ Undecorated

-- | Request headers allowing for invalid headers
--
-- NOTE: The HKD type
--
-- > RequestHeaders_ (Checked InvalidHeaders)
--
-- means that each field of type @HKD f a@ is of type
--
-- > Either InvalidHeaders a
--
-- (i.e., either valid or invalid).
--
-- See 'InvalidHeaderSynthesize' for an explanation of the @e@ parameter.
type RequestHeaders' e = RequestHeaders_ (Checked (InvalidHeaders e))

deriving stock instance Show    RequestHeaders
deriving stock instance Eq      RequestHeaders
deriving stock instance Generic RequestHeaders

deriving stock instance Show e => Show (RequestHeaders' e)
deriving stock instance Eq e   => Eq   (RequestHeaders' e)
-- We do not derive Generic for RequestHeaders', as doing so makes ghc confused
-- about the instance for RequestHeaders for some reason.

instance HKD.Traversable RequestHeaders_ where
  traverse :: forall (m :: * -> *) (f :: * -> *) (g :: * -> *).
Applicative m =>
(forall a. f a -> m (g a))
-> RequestHeaders_ (DecoratedWith f)
-> m (RequestHeaders_ (DecoratedWith g))
traverse forall a. f a -> m (g a)
f RequestHeaders_ (DecoratedWith f)
x =
      g (Maybe Timeout)
-> g (Maybe CompressionId)
-> g (Maybe (NonEmpty CompressionId))
-> g (Maybe ContentType)
-> g (Maybe MessageType)
-> g (Maybe ByteString)
-> g Bool
-> g (Maybe TraceContext)
-> g (Maybe Int)
-> CustomMetadataMap
-> g ()
-> RequestHeaders_ (DecoratedWith g)
HKD (DecoratedWith g) (Maybe Timeout)
-> HKD (DecoratedWith g) (Maybe CompressionId)
-> HKD (DecoratedWith g) (Maybe (NonEmpty CompressionId))
-> HKD (DecoratedWith g) (Maybe ContentType)
-> HKD (DecoratedWith g) (Maybe MessageType)
-> HKD (DecoratedWith g) (Maybe ByteString)
-> HKD (DecoratedWith g) Bool
-> HKD (DecoratedWith g) (Maybe TraceContext)
-> HKD (DecoratedWith g) (Maybe Int)
-> CustomMetadataMap
-> HKD (DecoratedWith g) ()
-> RequestHeaders_ (DecoratedWith g)
forall (f :: * -> *).
HKD f (Maybe Timeout)
-> HKD f (Maybe CompressionId)
-> HKD f (Maybe (NonEmpty CompressionId))
-> HKD f (Maybe ContentType)
-> HKD f (Maybe MessageType)
-> HKD f (Maybe ByteString)
-> HKD f Bool
-> HKD f (Maybe TraceContext)
-> HKD f (Maybe Int)
-> CustomMetadataMap
-> HKD f ()
-> RequestHeaders_ f
RequestHeaders
        (g (Maybe Timeout)
 -> g (Maybe CompressionId)
 -> g (Maybe (NonEmpty CompressionId))
 -> g (Maybe ContentType)
 -> g (Maybe MessageType)
 -> g (Maybe ByteString)
 -> g Bool
 -> g (Maybe TraceContext)
 -> g (Maybe Int)
 -> CustomMetadataMap
 -> g ()
 -> RequestHeaders_ (DecoratedWith g))
-> m (g (Maybe Timeout))
-> m (g (Maybe CompressionId)
      -> g (Maybe (NonEmpty CompressionId))
      -> g (Maybe ContentType)
      -> g (Maybe MessageType)
      -> g (Maybe ByteString)
      -> g Bool
      -> g (Maybe TraceContext)
      -> g (Maybe Int)
      -> CustomMetadataMap
      -> g ()
      -> RequestHeaders_ (DecoratedWith g))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (f (Maybe Timeout) -> m (g (Maybe Timeout))
forall a. f a -> m (g a)
f    (f (Maybe Timeout) -> m (g (Maybe Timeout)))
-> f (Maybe Timeout) -> m (g (Maybe Timeout))
forall a b. (a -> b) -> a -> b
$ RequestHeaders_ (DecoratedWith f)
-> HKD (DecoratedWith f) (Maybe Timeout)
forall (f :: * -> *). RequestHeaders_ f -> HKD f (Maybe Timeout)
requestTimeout             RequestHeaders_ (DecoratedWith f)
x)
        m (g (Maybe CompressionId)
   -> g (Maybe (NonEmpty CompressionId))
   -> g (Maybe ContentType)
   -> g (Maybe MessageType)
   -> g (Maybe ByteString)
   -> g Bool
   -> g (Maybe TraceContext)
   -> g (Maybe Int)
   -> CustomMetadataMap
   -> g ()
   -> RequestHeaders_ (DecoratedWith g))
-> m (g (Maybe CompressionId))
-> m (g (Maybe (NonEmpty CompressionId))
      -> g (Maybe ContentType)
      -> g (Maybe MessageType)
      -> g (Maybe ByteString)
      -> g Bool
      -> g (Maybe TraceContext)
      -> g (Maybe Int)
      -> CustomMetadataMap
      -> g ()
      -> RequestHeaders_ (DecoratedWith g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (f (Maybe CompressionId) -> m (g (Maybe CompressionId))
forall a. f a -> m (g a)
f    (f (Maybe CompressionId) -> m (g (Maybe CompressionId)))
-> f (Maybe CompressionId) -> m (g (Maybe CompressionId))
forall a b. (a -> b) -> a -> b
$ RequestHeaders_ (DecoratedWith f)
-> HKD (DecoratedWith f) (Maybe CompressionId)
forall (f :: * -> *).
RequestHeaders_ f -> HKD f (Maybe CompressionId)
requestCompression         RequestHeaders_ (DecoratedWith f)
x)
        m (g (Maybe (NonEmpty CompressionId))
   -> g (Maybe ContentType)
   -> g (Maybe MessageType)
   -> g (Maybe ByteString)
   -> g Bool
   -> g (Maybe TraceContext)
   -> g (Maybe Int)
   -> CustomMetadataMap
   -> g ()
   -> RequestHeaders_ (DecoratedWith g))
-> m (g (Maybe (NonEmpty CompressionId)))
-> m (g (Maybe ContentType)
      -> g (Maybe MessageType)
      -> g (Maybe ByteString)
      -> g Bool
      -> g (Maybe TraceContext)
      -> g (Maybe Int)
      -> CustomMetadataMap
      -> g ()
      -> RequestHeaders_ (DecoratedWith g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (f (Maybe (NonEmpty CompressionId))
-> m (g (Maybe (NonEmpty CompressionId)))
forall a. f a -> m (g a)
f    (f (Maybe (NonEmpty CompressionId))
 -> m (g (Maybe (NonEmpty CompressionId))))
-> f (Maybe (NonEmpty CompressionId))
-> m (g (Maybe (NonEmpty CompressionId)))
forall a b. (a -> b) -> a -> b
$ RequestHeaders_ (DecoratedWith f)
-> HKD (DecoratedWith f) (Maybe (NonEmpty CompressionId))
forall (f :: * -> *).
RequestHeaders_ f -> HKD f (Maybe (NonEmpty CompressionId))
requestAcceptCompression   RequestHeaders_ (DecoratedWith f)
x)
        m (g (Maybe ContentType)
   -> g (Maybe MessageType)
   -> g (Maybe ByteString)
   -> g Bool
   -> g (Maybe TraceContext)
   -> g (Maybe Int)
   -> CustomMetadataMap
   -> g ()
   -> RequestHeaders_ (DecoratedWith g))
-> m (g (Maybe ContentType))
-> m (g (Maybe MessageType)
      -> g (Maybe ByteString)
      -> g Bool
      -> g (Maybe TraceContext)
      -> g (Maybe Int)
      -> CustomMetadataMap
      -> g ()
      -> RequestHeaders_ (DecoratedWith g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (f (Maybe ContentType) -> m (g (Maybe ContentType))
forall a. f a -> m (g a)
f    (f (Maybe ContentType) -> m (g (Maybe ContentType)))
-> f (Maybe ContentType) -> m (g (Maybe ContentType))
forall a b. (a -> b) -> a -> b
$ RequestHeaders_ (DecoratedWith f)
-> HKD (DecoratedWith f) (Maybe ContentType)
forall (f :: * -> *).
RequestHeaders_ f -> HKD f (Maybe ContentType)
requestContentType         RequestHeaders_ (DecoratedWith f)
x)
        m (g (Maybe MessageType)
   -> g (Maybe ByteString)
   -> g Bool
   -> g (Maybe TraceContext)
   -> g (Maybe Int)
   -> CustomMetadataMap
   -> g ()
   -> RequestHeaders_ (DecoratedWith g))
-> m (g (Maybe MessageType))
-> m (g (Maybe ByteString)
      -> g Bool
      -> g (Maybe TraceContext)
      -> g (Maybe Int)
      -> CustomMetadataMap
      -> g ()
      -> RequestHeaders_ (DecoratedWith g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (f (Maybe MessageType) -> m (g (Maybe MessageType))
forall a. f a -> m (g a)
f    (f (Maybe MessageType) -> m (g (Maybe MessageType)))
-> f (Maybe MessageType) -> m (g (Maybe MessageType))
forall a b. (a -> b) -> a -> b
$ RequestHeaders_ (DecoratedWith f)
-> HKD (DecoratedWith f) (Maybe MessageType)
forall (f :: * -> *).
RequestHeaders_ f -> HKD f (Maybe MessageType)
requestMessageType         RequestHeaders_ (DecoratedWith f)
x)
        m (g (Maybe ByteString)
   -> g Bool
   -> g (Maybe TraceContext)
   -> g (Maybe Int)
   -> CustomMetadataMap
   -> g ()
   -> RequestHeaders_ (DecoratedWith g))
-> m (g (Maybe ByteString))
-> m (g Bool
      -> g (Maybe TraceContext)
      -> g (Maybe Int)
      -> CustomMetadataMap
      -> g ()
      -> RequestHeaders_ (DecoratedWith g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (f (Maybe ByteString) -> m (g (Maybe ByteString))
forall a. f a -> m (g a)
f    (f (Maybe ByteString) -> m (g (Maybe ByteString)))
-> f (Maybe ByteString) -> m (g (Maybe ByteString))
forall a b. (a -> b) -> a -> b
$ RequestHeaders_ (DecoratedWith f)
-> HKD (DecoratedWith f) (Maybe ByteString)
forall (f :: * -> *). RequestHeaders_ f -> HKD f (Maybe ByteString)
requestUserAgent           RequestHeaders_ (DecoratedWith f)
x)
        m (g Bool
   -> g (Maybe TraceContext)
   -> g (Maybe Int)
   -> CustomMetadataMap
   -> g ()
   -> RequestHeaders_ (DecoratedWith g))
-> m (g Bool)
-> m (g (Maybe TraceContext)
      -> g (Maybe Int)
      -> CustomMetadataMap
      -> g ()
      -> RequestHeaders_ (DecoratedWith g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (f Bool -> m (g Bool)
forall a. f a -> m (g a)
f    (f Bool -> m (g Bool)) -> f Bool -> m (g Bool)
forall a b. (a -> b) -> a -> b
$ RequestHeaders_ (DecoratedWith f) -> HKD (DecoratedWith f) Bool
forall (f :: * -> *). RequestHeaders_ f -> HKD f Bool
requestIncludeTE           RequestHeaders_ (DecoratedWith f)
x)
        m (g (Maybe TraceContext)
   -> g (Maybe Int)
   -> CustomMetadataMap
   -> g ()
   -> RequestHeaders_ (DecoratedWith g))
-> m (g (Maybe TraceContext))
-> m (g (Maybe Int)
      -> CustomMetadataMap -> g () -> RequestHeaders_ (DecoratedWith g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (f (Maybe TraceContext) -> m (g (Maybe TraceContext))
forall a. f a -> m (g a)
f    (f (Maybe TraceContext) -> m (g (Maybe TraceContext)))
-> f (Maybe TraceContext) -> m (g (Maybe TraceContext))
forall a b. (a -> b) -> a -> b
$ RequestHeaders_ (DecoratedWith f)
-> HKD (DecoratedWith f) (Maybe TraceContext)
forall (f :: * -> *).
RequestHeaders_ f -> HKD f (Maybe TraceContext)
requestTraceContext        RequestHeaders_ (DecoratedWith f)
x)
        m (g (Maybe Int)
   -> CustomMetadataMap -> g () -> RequestHeaders_ (DecoratedWith g))
-> m (g (Maybe Int))
-> m (CustomMetadataMap
      -> g () -> RequestHeaders_ (DecoratedWith g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (f (Maybe Int) -> m (g (Maybe Int))
forall a. f a -> m (g a)
f    (f (Maybe Int) -> m (g (Maybe Int)))
-> f (Maybe Int) -> m (g (Maybe Int))
forall a b. (a -> b) -> a -> b
$ RequestHeaders_ (DecoratedWith f)
-> HKD (DecoratedWith f) (Maybe Int)
forall (f :: * -> *). RequestHeaders_ f -> HKD f (Maybe Int)
requestPreviousRpcAttempts RequestHeaders_ (DecoratedWith f)
x)
        m (CustomMetadataMap -> g () -> RequestHeaders_ (DecoratedWith g))
-> m CustomMetadataMap
-> m (g () -> RequestHeaders_ (DecoratedWith g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (CustomMetadataMap -> m CustomMetadataMap
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (CustomMetadataMap -> m CustomMetadataMap)
-> CustomMetadataMap -> m CustomMetadataMap
forall a b. (a -> b) -> a -> b
$ RequestHeaders_ (DecoratedWith f) -> CustomMetadataMap
forall (f :: * -> *). RequestHeaders_ f -> CustomMetadataMap
requestMetadata            RequestHeaders_ (DecoratedWith f)
x)
        m (g () -> RequestHeaders_ (DecoratedWith g))
-> m (g ()) -> m (RequestHeaders_ (DecoratedWith g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (f () -> m (g ())
forall a. f a -> m (g a)
f    (f () -> m (g ())) -> f () -> m (g ())
forall a b. (a -> b) -> a -> b
$ RequestHeaders_ (DecoratedWith f) -> HKD (DecoratedWith f) ()
forall (f :: * -> *). RequestHeaders_ f -> HKD f ()
requestUnrecognized        RequestHeaders_ (DecoratedWith f)
x)