packages feed

serverless-haskell 0.6.0 → 0.6.1

raw patch · 5 files changed

+85/−44 lines, 5 files

Files

README.md view
@@ -83,10 +83,20 @@   You can test the function and see the invocation results with `sls invoke   myfunc`. +  To invoke the function locally, use `sls invoke local -f myfunc`.++### API Gateway++This plugin supports handling API Gateway requests. Declare the HTTP events+normally in `serverless.yml` and use+[AWSLambda.Events.APIGateway](https://hackage.haskell.org/package/serverless-haskell/docs/AWSLambda-Events-APIGateway.html)+in the handler to process them.++[Serverless Offline] can be used for local testing of API Gateway requests.+ ### Notes  * `sls deploy function` is [not supported yet](https://github.com/seek-oss/serverless-haskell/issues/20).-* `sls invoke local` is [not supported yet](https://github.com/seek-oss/serverless-haskell/issues/32). * Only AWS Lambda is supported at the moment. Other cloud providers would   require different JavaScript wrappers to be implemented. @@ -128,4 +138,5 @@ [jq]: https://stedolan.github.io/jq/ [NPM]: https://www.npmjs.com/ [Serverless]: https://serverless.com/framework/+[Serverless Offline]: https://github.com/dherault/serverless-offline [Stack]: https://haskellstack.org
serverless-haskell.cabal view
@@ -2,10 +2,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: a288b7dc8892f8e7cdb3d9e4d980ac5efaf104fe9c7a57a274c93d42991a2145+-- hash: 0fa49464ad722f9e904826775d750cd559324657f0fb63fff4212c4e818e7ba8  name:           serverless-haskell-version:        0.6.0+version:        0.6.1 synopsis:       Deploying Haskell code onto AWS Lambda using Serverless description:    Utilities to help process the events from AWS Lambda when deployed with the serverless-haskell plugin. category:       AWS, Cloud, Network
src/AWSLambda.hs view
@@ -1,5 +1,5 @@ {-|-Module      : AWSLambda.Handler+Module      : AWSLambda Stability   : experimental Portability : POSIX @@ -44,6 +44,17 @@    You can test the function and see the invocation results with @sls invoke   myfunc@.++  To invoke the function locally, use @sls invoke local -f myfunc@.++= API Gateway++This plugin supports handling API Gateway requests. Declare the HTTP events+normally in @serverless.yml@ and use 'AWSLambda.Events.APIGateway' in the+handler to process them.++<https://github.com/dherault/serverless-offline Serverless Offline> can be used+for local testing of API Gateway requests.  = Additional features 
src/AWSLambda/Events/APIGateway.hs view
@@ -8,6 +8,19 @@ Description: Types for APIGateway Lambda requests and responses  Based on https://github.com/aws/aws-lambda-dotnet/tree/master/Libraries/src/Amazon.Lambda.APIGatewayEvents++To enable processing of API Gateway events, use the @events@ key in+@serverless.yml@ as usual:++> functions:+>   myapifunc:+>     handler: mypackage.mypackage-exe+>     events:+>       - http:+>           path: hello/{name}+>           method: get++Then use 'apiGatewayMain' in the handler to process the requests. -} module AWSLambda.Events.APIGateway where @@ -200,36 +213,36 @@ responseBodyBinary :: Setter' (APIGatewayProxyResponse Base64) (Maybe ByteString) responseBodyBinary = responseBody . mapping _Base64 --- | Process incoming events from @serverless-haskell@ using a provided--- function.------ This is a specialisation of lambdaMain for API Gateway.------ The handler receives the input event given to the AWS Lambda function, and--- its return value is returned from the function.------ This is intended to be used as @main@, for example:------ > import AWSLambda.Events.APIGateway--- > import Control.Lens--- > import Data.Aeson--- > import Data.Aeson.Embedded--- >--- > main = apiGatewayMain handler--- >--- > handler :: APIGatewayProxyRequest (Embedded Value) -> IO (APIGatewayProxyResponse (Embedded [Int]))--- > handler request = do--- >   putStrLn "This should go to logs"--- >   print $ request ^. requestBody--- >   pure $ responseOK & responseBodyEmbedded ?~ [1, 2, 3]------ The type parameters @reqBody@ and @resBody@ represent the types of request and response body, respectively.--- The @FromText@ and @ToText@ contraints are required because these values come from string fields--- in the request and response JSON objects.--- To get direct access to the body string, use @Text@ as the parameter type.--- To treat the body as a stringified embedded JSON value, use @Embedded a@, where @a@ has the--- appropriate @FromJSON@ or @ToJSON@ instances.--- To treat the body as base 64 encoded binary use @Base64@.+{-| Process incoming events from @serverless-haskell@ using a provided function.++This is a specialisation of 'lambdaMain' for API Gateway.++The handler receives the input event given to the AWS Lambda function, and+its return value is returned from the function.++This is intended to be used as @main@, for example:++> import AWSLambda.Events.APIGateway+> import Control.Lens+> import Data.Aeson+> import Data.Aeson.Embedded+>+> main = apiGatewayMain handler+>+> handler :: APIGatewayProxyRequest (Embedded Value) -> IO (APIGatewayProxyResponse (Embedded [Int]))+> handler request = do+>   putStrLn "This should go to logs"+>   print $ request ^. requestBody+>   pure $ responseOK & responseBodyEmbedded ?~ [1, 2, 3]++The type parameters @reqBody@ and @resBody@ represent the types of request and response body, respectively.+The @FromText@ and @ToText@ contraints are required because these values come from string fields+in the request and response JSON objects.+To get direct access to the body string, use @Text@ as the parameter type.+To treat the body as a stringified embedded JSON value, use @Embedded a@, where @a@ has the+appropriate @FromJSON@ or @ToJSON@ instances.+To treat the body as base 64 encoded binary use @Base64@.+-} apiGatewayMain   :: (FromText reqBody, ToText resBody)   => (APIGatewayProxyRequest reqBody -> IO (APIGatewayProxyResponse resBody)) -- ^ Function to process the event
src/AWSLambda/Handler.hs view
@@ -5,11 +5,13 @@  Entry point for AWS Lambda handlers deployed with @serverless-haskell@ plugin. -}+{-# LANGUAGE TypeApplications #-}+ module AWSLambda.Handler   ( lambdaMain   ) where -import Control.Exception (bracket)+import Control.Exception (bracket, try)  import qualified Data.Aeson as Aeson import qualified Data.Aeson.Text as Aeson@@ -18,10 +20,11 @@  import qualified Data.Text.Lazy.IO as Text -import GHC.IO.Handle (Handle, hClose)+import GHC.IO.Handle+       (BufferMode(..), Handle, hClose, hSetBuffering) -import System.Environment (lookupEnv) import System.IO (stdout)+import System.Posix.Files (getFdStatus) import System.Posix.IO (fdToHandle) import System.Posix.Types (Fd(..)) @@ -88,15 +91,18 @@         Text.hPutStrLn resultChannel $ Aeson.encodeToLazyText result         pure () --- | Invoke an action with the handle to write the results to. On AWS Lambda,--- use the channel opened by the JavaScript wrapper, otherwise use standard--- output.+-- | Invoke an action with the handle to write the results to. If called by the+-- JavaScript wrapper, use the channel opened by it, otherwise use standard+-- output. Also set line buffering on standard output for AWS Lambda so the logs+-- are output in a timely manner. withResultChannel :: (Handle -> IO r) -> IO r withResultChannel act = do-  lambdaFunctionName <- lookupEnv "AWS_LAMBDA_FUNCTION_NAME"-  case lambdaFunctionName of-    Just _ -> bracket (fdToHandle communicationFd) hClose act-    Nothing -> act stdout+  commStatus <- try @IOError $ getFdStatus communicationFd+  case commStatus of+    Right _ -> do+      hSetBuffering stdout LineBuffering+      bracket (fdToHandle communicationFd) hClose act+    Left _ -> act stdout  -- | File descriptor opened by the JavaScript wrapper to listen for the results communicationFd :: Fd