DEV Community

Mac
Mac

Posted on • Edited on

API Gateway and Lambda

Below is an example of how to create API Gateway that trigger Lambda by using 3 difference Infrastructure as Code tools.

AWS CloudFormation

Example, https://github.com/MacKittipat/mac-cloudformation-helloworld/blob/master/cloudformation.yaml

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  LambdaFunctionName:
    Type: String
    Default: HelloWorld
Resources:
  # API Gateway
  ApiGatewayRestApiHelloWorld:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: HelloWorldApi
  ApiGatewayResourceHelloWorld:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref ApiGatewayRestApiHelloWorld
      ParentId: !GetAtt ApiGatewayRestApiHelloWorld.RootResourceId
      PathPart: !Ref LambdaFunctionName
  ApiGatewayMethodHelloWorld:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      HttpMethod: ANY
      ResourceId: !Ref ApiGatewayResourceHelloWorld
      RestApiId: !Ref ApiGatewayRestApiHelloWorld
      ApiKeyRequired: false
      AuthorizationType: NONE
      MethodResponses:
        - StatusCode: '200'
      Integration:
        ConnectionType: INTERNET
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunctionHelloWorld.Arn}/invocations'
  ApiGatewayDeploymentHelloWorld:
    DependsOn: ApiGatewayMethodHelloWorld
    Type: 'AWS::ApiGateway::Deployment'
    Properties:
      RestApiId: !Ref ApiGatewayRestApiHelloWorld
      StageName: prod
  # Lambda Function
  LambdaFunctionHelloWorld:
    Type: 'AWS::Lambda::Function'
    Properties:
      FunctionName: !Ref LambdaFunctionName
      Code:
        ZipFile: |
          exports.handler = async function(event) {
            const response = {
              statusCode: 200,
              body: "Hello World. Build with CloudFormation",
            };
            return response;
          }
      Handler: index.handler
      Role: {ROLE}
      Runtime: nodejs12.x
  LambdaPermissionHelloWorld:
    Type: 'AWS::Lambda::Permission'
    Properties:
      FunctionName: !GetAtt LambdaFunctionHelloWorld.Arn
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGatewayRestApiHelloWorld}/*/*/${LambdaFunctionName}'

Serverless Framework

Example, https://github.com/MacKittipat/mac-serverless-helloearth

provider:
  name: aws
  runtime: nodejs12.x
  stage: dev
  region: ap-southeast-1
functions:
  hello:
    handler: handler.helloEarth
    events:
      - http:
          path: HelloEarth
          method: get

AWS CDK

Example, https://github.com/MacKittipat/mac-cdk-helloplanet

import * as cdk from '@aws-cdk/core';
import * as lambda from '@aws-cdk/aws-lambda';
import * as apiGateway from '@aws-cdk/aws-apigateway';

export class MacCdkHelloplanetStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const functionName = 'HelloPlanet';
    const lambdaFunction = new lambda.Function(this, functionName, {
      runtime: lambda.Runtime.NODEJS_12_X,
      handler: 'index.handler',
      code: lambda.Code.fromAsset('resources'),
    });

    const gatewayRestApi = new apiGateway.RestApi(this, functionName + 'Api', {
      restApiName: functionName + 'Api',
      deployOptions: {
        stageName: 'prod'
      }
    })

    const gatewayLambdaIntegration = new apiGateway.LambdaIntegration(lambdaFunction, {
      allowTestInvoke: false
    });

    const gatewayResource = gatewayRestApi.root.addResource(functionName);
    gatewayResource.addMethod("GET", gatewayLambdaIntegration)

  }
}

Top comments (4)

Collapse
 
andrewdmay profile image
Andrew May

I would add the AWS Serverless Application Model (SAM) to that list.
Behind the scenes it's mostly CloudFormation, but using a transformation that allows you to configure a lambda function and it's event sources in a more compact way very similar to the Serverless Framework.
Like Serverless it comes with a CLI and makes it easy to deploy and update lambda functions. It also has some ability to run your Lambda functions locally within official AWS Docker containers, and even serve a light form of API Gateway (REST only currently) locally.

Collapse
 
mackittipat profile image
Mac

Thanks for sharing Andrew. It is very interesting especially it can run Lambda and API gateway locally.
I am just curious that will running locally works if my Lambda need to connect to SQS and DynamoDB on AWS?

Collapse
 
andrewdmay profile image
Andrew May

For talking to other AWS services you can provide it with an AWS profile to use (see the --profile option on sam invoke local and sam local start-api) and it will then use those services in your AWS account.

It is possible, but somewhat more complicated to run test versions of DynamoDB and mock versions of some services in Docker (see the localstack project) - but requires you to run the services in the same docker network and override the endpoint that is used to communicate with the services.

If you're just consuming messages from SQS, the sam local generate-event command can be used to create test events to feed to sam local invoke.

Thread Thread
 
mackittipat profile image
Mac

Thanks Andrew