diff --git a/ChangeLog.md b/ChangeLog.md index 7d11973..682e394 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,12 +1,18 @@ # Changelog for aws-lambda-haskell-runtime-wai +## 2.0.2 + +* Make registering multiple wai handlers possible (via `waiHandler`). +* Make registering multiple handlers with multiple Wai Applications possible (via `runMultipleWaiApplications`). +* Use version `4.1.1` of `aws-lambda-haskell-runtime`. + ## 2.0.1 -* Using version `4.1.0` of `aws-lambda-haskell-runtime` that fixes [#101](https://github.com/theam/aws-lambda-haskell-runtime/issues/101). +* Use version `4.1.0` of `aws-lambda-haskell-runtime` that fixes [#101](https://github.com/theam/aws-lambda-haskell-runtime/issues/101). ## 2.0.0 -* Using version [`4.0.0`](https://github.com/theam/aws-lambda-haskell-runtime/pull/97) of `aws-lambda-haskell-runtime`. +* Use version [`4.0.0`](https://github.com/theam/aws-lambda-haskell-runtime/pull/97) of `aws-lambda-haskell-runtime`. * New handler types that allow you to support ALB or even API Gateway + ALB at once. ## 1.0.3 diff --git a/aws-lambda-haskell-runtime-wai.cabal b/aws-lambda-haskell-runtime-wai.cabal index 863dd40..2ddbdfe 100644 --- a/aws-lambda-haskell-runtime-wai.cabal +++ b/aws-lambda-haskell-runtime-wai.cabal @@ -1,13 +1,13 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.33.0. +-- This file has been generated from package.yaml by hpack version 0.34.4. -- -- see: https://github.com/sol/hpack -- --- hash: 7ac059dff419276eecdd9bc3935ba4601d6b8e0ea70b452264ca490df133487a +-- hash: 4f70c32a7c39e85a18faf7ec170f65c5e46116d8f23661e3aa358ca1b1a913b9 name: aws-lambda-haskell-runtime-wai -version: 2.0.1 +version: 2.0.2 synopsis: Run wai applications on AWS Lambda description: Please see the README on GitHub at category: AWS diff --git a/package.yaml b/package.yaml index fca22fc..d168d33 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,5 @@ name: aws-lambda-haskell-runtime-wai -version: 2.0.1 +version: 2.0.2 github: "eir-forsakring/aws-lambda-haskell-runtime-wai" license: BSD3 author: "Dobromir Nikolov" diff --git a/src/Aws/Lambda/Wai.hs b/src/Aws/Lambda/Wai.hs index c33fb19..bcad37a 100644 --- a/src/Aws/Lambda/Wai.hs +++ b/src/Aws/Lambda/Wai.hs @@ -14,11 +14,14 @@ module Aws.Lambda.Wai ALBWaiHandler, ignoreALBPathPart, ignoreNothing, + waiHandler, + runMultipleWaiApplications, ) where import Aws.Lambda import Control.Concurrent.MVar +import Control.Monad (forM, forM_) import Data.Aeson import Data.Aeson.Types import Data.Bifunctor (Bifunctor (bimap)) @@ -27,6 +30,7 @@ import Data.ByteString (ByteString) import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as BL import qualified Data.CaseInsensitive as CI +import Data.HashMap.Strict (HashMap) import qualified Data.HashMap.Strict as HMap import Data.IORef import qualified Data.IP as IP @@ -48,6 +52,8 @@ type ApiGatewayWaiHandler = ApiGatewayRequest Text -> Context Application -> IO type ALBWaiHandler = ALBRequest Text -> Context Application -> IO (Either (ALBResponse Text) (ALBResponse Text)) +type GenericWaiHandler = Value -> Context Application -> IO (Either Value Value) + newtype ALBIgnoredPathPortion = ALBIgnoredPathPortion {unALBIgnoredPathPortion :: Text} data WaiLambdaProxyType @@ -62,21 +68,57 @@ runWaiAsProxiedHttpLambda :: IO () runWaiAsProxiedHttpLambda options ignoredAlbPath handlerName mkApp = runLambdaHaskellRuntime options mkApp id $ - addStandaloneLambdaHandler handlerName $ \(request :: Value) context -> - case parse parseIsAlb request of - Success isAlb -> do - if isAlb - then case fromJSON @(ALBRequest Text) request of - Success albRequest -> - bimap toJSON toJSON <$> albWaiHandler ignoredAlbPath albRequest context - Error err -> error $ "Could not parse the request as a valid ALB request: " <> err - else case fromJSON @(ApiGatewayRequest Text) request of - Success apiGwRequest -> - bimap toJSON toJSON <$> apiGatewayWaiHandler apiGwRequest context - Error err -> error $ "Could not parse the request as a valid API Gateway request: " <> err - Error err -> - error $ - "Could not parse the request as a valid API Gateway or ALB proxy request: " <> err + addStandaloneLambdaHandler handlerName (waiHandler ignoredAlbPath) + +runMultipleWaiApplications :: + DispatcherOptions -> + HashMap HandlerName (Maybe ALBIgnoredPathPortion, IO Application) -> + IO () +runMultipleWaiApplications options handlersAndApps = do + runLambdaHaskellRuntime options initializeApplications id $ + forM_ (HMap.keys handlersAndApps) $ \handler -> + addStandaloneLambdaHandler handler $ \request context -> + multiApplicationWaiHandler handler request context + where + initializeApplications :: IO (HashMap HandlerName (Maybe ALBIgnoredPathPortion, Application)) + initializeApplications = do + HMap.fromList + <$> forM + (HMap.toList handlersAndApps) + (\(handler, (alb, mkApp)) -> mkApp >>= \app -> return (handler, (alb, app))) + +multiApplicationWaiHandler :: + HandlerName -> + Value -> + Context (HashMap HandlerName (Maybe ALBIgnoredPathPortion, Application)) -> + IO (Either Value Value) +multiApplicationWaiHandler handlerName request context = do + appMay <- HMap.lookup handlerName <$> readIORef (customContext context) + case appMay of + Just (ignoredAlbPart, app) -> do + applicationRef <- newIORef app + waiHandler ignoredAlbPart request (context {customContext = applicationRef}) + Nothing -> + fail $ "No application was registered for handler '" <> T.unpack (unHandlerName handlerName) <> "'." + +waiHandler :: + Maybe ALBIgnoredPathPortion -> + GenericWaiHandler +waiHandler ignoredAlbPath request context = + case parse parseIsAlb request of + Success isAlb -> do + if isAlb + then case fromJSON @(ALBRequest Text) request of + Success albRequest -> + bimap toJSON toJSON <$> albWaiHandler ignoredAlbPath albRequest context + Error err -> error $ "Could not parse the request as a valid ALB request: " <> err + else case fromJSON @(ApiGatewayRequest Text) request of + Success apiGwRequest -> + bimap toJSON toJSON <$> apiGatewayWaiHandler apiGwRequest context + Error err -> error $ "Could not parse the request as a valid API Gateway request: " <> err + Error err -> + error $ + "Could not parse the request as a valid API Gateway or ALB proxy request: " <> err where parseIsAlb :: Value -> Parser Bool parseIsAlb = withObject "Request" $ \obj -> do diff --git a/stack.yaml b/stack.yaml index 8bd6d99..5fab919 100644 --- a/stack.yaml +++ b/stack.yaml @@ -17,7 +17,7 @@ # # resolver: ./custom-snapshot.yaml # resolver: https://example.com/snapshots/2018-01-01.yaml -resolver: lts-16.12 +resolver: nightly-2021-04-06 # User packages to be built. # Various formats can be used as shown in the example below. @@ -40,7 +40,8 @@ packages: # commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a # extra-deps: -- aws-lambda-haskell-runtime-4.1.0@sha256:4fbf9855326ed0173c3ef27c006412c8da46f84b0566fa92a44ad0e988432d82,2916 +- aws-lambda-haskell-runtime-4.1.1@sha256:c3b3452d3a7f36950c22760fe44b51d49b43624fa3a0253e5bfc3d94809bb8fd,3024 +- safe-exceptions-checked-0.1.0@sha256:ae142f284c6b102f0e7606a69a5719f4f72771d9cc353af72fa4484326689100,1603 # Override default flag values for local packages and extra-deps # flags: {} diff --git a/stack.yaml.lock b/stack.yaml.lock index 3bbf6da..4f43882 100644 --- a/stack.yaml.lock +++ b/stack.yaml.lock @@ -5,15 +5,22 @@ packages: - completed: - hackage: aws-lambda-haskell-runtime-4.1.0@sha256:4fbf9855326ed0173c3ef27c006412c8da46f84b0566fa92a44ad0e988432d82,2916 + hackage: aws-lambda-haskell-runtime-4.1.1@sha256:c3b3452d3a7f36950c22760fe44b51d49b43624fa3a0253e5bfc3d94809bb8fd,3024 pantry-tree: size: 1453 - sha256: c01167c71d6e25a33b822629d5efc50818589e33e5341ee1bea1bb4e2c59f9c6 + sha256: b7e8426edb0b5d06713a26362308abbec03379e1f3ad9c6d63973088ad75cf62 original: - hackage: aws-lambda-haskell-runtime-4.1.0@sha256:4fbf9855326ed0173c3ef27c006412c8da46f84b0566fa92a44ad0e988432d82,2916 + hackage: aws-lambda-haskell-runtime-4.1.1@sha256:c3b3452d3a7f36950c22760fe44b51d49b43624fa3a0253e5bfc3d94809bb8fd,3024 +- completed: + hackage: safe-exceptions-checked-0.1.0@sha256:ae142f284c6b102f0e7606a69a5719f4f72771d9cc353af72fa4484326689100,1603 + pantry-tree: + size: 298 + sha256: d1f8ba50967547f26cdc37cbc64bdc85af57d856986876a6a5767a61977bc299 + original: + hackage: safe-exceptions-checked-0.1.0@sha256:ae142f284c6b102f0e7606a69a5719f4f72771d9cc353af72fa4484326689100,1603 snapshots: - completed: - size: 532377 - url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/16/12.yaml - sha256: f914cfa23fef85bdf895e300a8234d9d0edc2dbec67f4bc9c53f85867c50eab6 - original: lts-16.12 + size: 576531 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/nightly/2021/4/6.yaml + sha256: 6ce168aed6ba23cfe148061587ba1c0f24a09d4cad8b1a5a29b21878e33d6ef4 + original: nightly-2021-04-06