{-# LANGUAGE GADTs #-}

-- | Publishing of results/errors back to the
-- AWS Lambda runtime API
module Aws.Lambda.Runtime.Publish
  ( result,
    invocationError,
    parsingError,
    runtimeInitError,
  )
where

import qualified Aws.Lambda.Runtime.API.Endpoints as Endpoints
import Aws.Lambda.Runtime.Common
import Aws.Lambda.Runtime.Context (Context (..))
import qualified Aws.Lambda.Runtime.Error as Error
import Aws.Lambda.Runtime.StandaloneLambda.Types
import Control.Monad (void)
import Data.Aeson
import qualified Data.ByteString.Lazy as LBS
import Data.Text (Text, unpack)
import qualified Data.Text.Encoding as T
import qualified Network.HTTP.Client as Http

-- | Publishes the result back to AWS Lambda
result :: LambdaResult handlerType -> Text -> Context context -> Http.Manager -> IO ()
result :: forall (handlerType :: HandlerType) context.
LambdaResult handlerType
-> Text -> Context context -> Manager -> IO ()
result LambdaResult handlerType
lambdaResult Text
lambdaApi Context context
context Manager
manager = do
  let Endpoints.Endpoint Text
endpoint = Text -> Text -> Endpoint
Endpoints.response Text
lambdaApi (forall context. Context context -> Text
awsRequestId Context context
context)
  Request
rawRequest <- forall (m :: * -> *). MonadThrow m => String -> m Request
Http.parseRequest forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
unpack forall a b. (a -> b) -> a -> b
$ Text
endpoint

  let requestBody :: RequestBody
requestBody = case LambdaResult handlerType
lambdaResult of
        (StandaloneLambdaResult (StandaloneLambdaResponseBodyPlain Text
res)) ->
          Method -> RequestBody
Http.RequestBodyBS (Text -> Method
T.encodeUtf8 Text
res)
        (StandaloneLambdaResult (StandaloneLambdaResponseBodyJson ByteString
res)) ->
          ByteString -> RequestBody
Http.RequestBodyLBS ByteString
res
        (APIGatewayResult ApiGatewayResponse ApiGatewayResponseBody
res) -> ByteString -> RequestBody
Http.RequestBodyLBS (forall a. ToJSON a => a -> ByteString
encode ApiGatewayResponse ApiGatewayResponseBody
res)
        (ALBResult ALBResponse ALBResponseBody
res) -> ByteString -> RequestBody
Http.RequestBodyLBS (forall a. ToJSON a => a -> ByteString
encode ALBResponse ALBResponseBody
res)
      request :: Request
request =
        Request
rawRequest
          { method :: Method
Http.method = Method
"POST",
            requestBody :: RequestBody
Http.requestBody = RequestBody
requestBody
          }

  forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ Request -> Manager -> IO (Response ())
Http.httpNoBody Request
request Manager
manager

-- | Publishes an invocation error back to AWS Lambda
invocationError :: Error.Invocation -> Text -> Context context -> Http.Manager -> IO ()
invocationError :: forall context.
Invocation -> Text -> Context context -> Manager -> IO ()
invocationError (Error.Invocation ByteString
err) Text
lambdaApi Context context
context =
  forall context.
ByteString -> Endpoint -> Context context -> Manager -> IO ()
publish ByteString
err (Text -> Text -> Endpoint
Endpoints.invocationError Text
lambdaApi forall a b. (a -> b) -> a -> b
$ forall context. Context context -> Text
awsRequestId Context context
context) Context context
context

-- | Publishes a parsing error back to AWS Lambda
parsingError :: Error.Parsing -> Text -> Context context -> Http.Manager -> IO ()
parsingError :: forall context.
Parsing -> Text -> Context context -> Manager -> IO ()
parsingError Parsing
err Text
lambdaApi Context context
context =
  forall context.
ByteString -> Endpoint -> Context context -> Manager -> IO ()
publish
    (forall a. ToJSON a => a -> ByteString
encode Parsing
err)
    (Text -> Text -> Endpoint
Endpoints.invocationError Text
lambdaApi forall a b. (a -> b) -> a -> b
$ forall context. Context context -> Text
awsRequestId Context context
context)
    Context context
context

-- | Publishes a runtime initialization error back to AWS Lambda
runtimeInitError :: ToJSON err => err -> Text -> Context context -> Http.Manager -> IO ()
runtimeInitError :: forall err context.
ToJSON err =>
err -> Text -> Context context -> Manager -> IO ()
runtimeInitError err
err Text
lambdaApi =
  forall context.
ByteString -> Endpoint -> Context context -> Manager -> IO ()
publish (forall a. ToJSON a => a -> ByteString
encode err
err) (Text -> Endpoint
Endpoints.runtimeInitError Text
lambdaApi)

publish :: LBS.ByteString -> Endpoints.Endpoint -> Context context -> Http.Manager -> IO ()
publish :: forall context.
ByteString -> Endpoint -> Context context -> Manager -> IO ()
publish ByteString
err (Endpoints.Endpoint Text
endpoint) Context context
_context Manager
manager = do
  Request
rawRequest <- forall (m :: * -> *). MonadThrow m => String -> m Request
Http.parseRequest forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
unpack forall a b. (a -> b) -> a -> b
$ Text
endpoint

  let requestBody :: RequestBody
requestBody = ByteString -> RequestBody
Http.RequestBodyLBS ByteString
err
      request :: Request
request =
        Request
rawRequest
          { method :: Method
Http.method = Method
"POST",
            requestBody :: RequestBody
Http.requestBody = RequestBody
requestBody
          }

  forall (f :: * -> *) a. Functor f => f a -> f ()
void forall a b. (a -> b) -> a -> b
$ Request -> Manager -> IO (Response ())
Http.httpNoBody Request
request Manager
manager