{-# 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 :: 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 (Context context -> Text
forall context. Context context -> Text
awsRequestId Context context
context)
  Request
rawRequest <- String -> IO Request
forall (m :: * -> *). MonadThrow m => String -> m Request
Http.parseRequest (String -> IO Request) -> (Text -> String) -> Text -> IO Request
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
unpack (Text -> IO Request) -> Text -> IO Request
forall a b. (a -> b) -> a -> b
$ Text
endpoint

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

  IO (Response ()) -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO (Response ()) -> IO ()) -> IO (Response ()) -> IO ()
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 :: Invocation -> Text -> Context context -> Manager -> IO ()
invocationError (Error.Invocation ByteString
err) Text
lambdaApi Context context
context =
  ByteString -> Endpoint -> Context context -> Manager -> IO ()
forall context.
ByteString -> Endpoint -> Context context -> Manager -> IO ()
publish ByteString
err (Text -> Text -> Endpoint
Endpoints.invocationError Text
lambdaApi (Text -> Endpoint) -> Text -> Endpoint
forall a b. (a -> b) -> a -> b
$ Context context -> Text
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 :: Parsing -> Text -> Context context -> Manager -> IO ()
parsingError Parsing
err Text
lambdaApi Context context
context =
  ByteString -> Endpoint -> Context context -> Manager -> IO ()
forall context.
ByteString -> Endpoint -> Context context -> Manager -> IO ()
publish
    (Parsing -> ByteString
forall a. ToJSON a => a -> ByteString
encode Parsing
err)
    (Text -> Text -> Endpoint
Endpoints.invocationError Text
lambdaApi (Text -> Endpoint) -> Text -> Endpoint
forall a b. (a -> b) -> a -> b
$ Context context -> Text
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 :: err -> Text -> Context context -> Manager -> IO ()
runtimeInitError err
err Text
lambdaApi =
  ByteString -> Endpoint -> Context context -> Manager -> IO ()
forall context.
ByteString -> Endpoint -> Context context -> Manager -> IO ()
publish (err -> ByteString
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 :: ByteString -> Endpoint -> Context context -> Manager -> IO ()
publish ByteString
err (Endpoints.Endpoint Text
endpoint) Context context
_context Manager
manager = do
  Request
rawRequest <- String -> IO Request
forall (m :: * -> *). MonadThrow m => String -> m Request
Http.parseRequest (String -> IO Request) -> (Text -> String) -> Text -> IO Request
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
unpack (Text -> IO Request) -> Text -> IO Request
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 :: ByteString
Http.method = ByteString
"POST",
            requestBody :: RequestBody
Http.requestBody = RequestBody
requestBody
          }

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