Cloudformation: Lambda with HTTP API Gateway
Tags: aws, lambda
Published: 2021-09-14 21:15:43

##Hey, Welcome!
In this post I am going to share how you can quickly setup a cloudformation stack with HTTP API Gateway proxying requests to serverless lambda function.

You can read in my [previous post] (https://dev.to/lubanasachin/cloudformation-http-api-gateway-with-dns-4kg5) on setting up an HTTP API gateway with custom domain.

To make it simpler, I will break it down into multiple steps.

If you are just interested in the `yaml` template simply scroll down to the end.

**Step 1: Create serverless lambda function**

```yaml
  DemoFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: "nodejs12.x"
      InlineCode: |
        exports.handler = function(event, context, callback) {
            console.log(event);
            const response = {
                statusCode: 200,
                body: JSON.stringify('Hello Node rule 1')
            };
            callback(null, response);
        };
```

The above code creates [serverless lambda] (https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) function.

This lambda function basically uses 
* `nodejs12.x` as [runtime] (https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html)
* inline source code which can be `CodeUri` property that reference the source code from file

**Step 2: Enable lambda invoke permission**

```yaml
  DemoLambdaInvokePermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref DemoFunction
      Action: "lambda:InvokeFunction"
      Principal: apigateway.amazonaws.com
```

The above code enables the lambda invoke from an api gateway You can read more about the [lambda invoke] (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-permission.html) permission.

**Step 3: Create lambda proxy integration**

```yaml
  DemoIntegration:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
      ApiId: !Ref DemoHttpApi
      Description: Lambda proxy integration
      IntegrationType: AWS_PROXY
      IntegrationMethod: GET
      PayloadFormatVersion: "2.0"
      IntegrationUri: !Sub 'arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DemoFunction.Arn}/invocations'
```

The above code integrates the lambda function with an HTTP api gateway.
You can read more about the lambda proxy integration [here] (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigatewayv2-integration.html)

**Step 4: Create api route**

```yaml
  DemoApiRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
      ApiId: !Ref DemoHttpApi
      RouteKey: "GET /demo"
      AuthorizationType: AWS_IAM
      Target: !Join
        - /
        - - integrations
          - !Ref DemoIntegration
```

The above code creates an [api route] (https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigatewayv2-route.html) with requests targeted to the lambda proxy integration.

I have configured authorization type as `AWS_IAM` which means the calling client (IAM role) must have permission to execute API gateway.

I use this API gateway for internal service communication where the calling site is another lambda function.

It implies that my lambda function `X` requests data from api gateway which proxies the requests to lambda function `Y` and this request is authenticated using `AWS_IAM` mechanism.

**Step 5: Call site lambda function**

```yaml
  DemoCallFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: nodejs12.x
      CodeUri: dist/lambda/demoCall/
      Policies:
        - AmazonAPIGatewayInvokeFullAccess
```

That is all you need to integrate lambda function with an HTTP api gateway.

You can use the below template to create cloudformation stack with all the above resources we talked about.

```yaml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Lambda with HTTP API gateway demo stack

Resources:
  ##########################################
  ##  create your API gateway resources   ##
  ##  as described in my previous post    ##
  ##########################################

  DemoFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: "nodejs12.x"
      InlineCode: |
        exports.handler = function(event, context, callback) {
            console.log(event);
            const response = {
                statusCode: 200,
                body: JSON.stringify('Hello Node rule 1')
            };
            callback(null, response);
        };

  DemoLambdaInvokePermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref DemoFunction
      Action: "lambda:InvokeFunction"
      Principal: apigateway.amazonaws.com

  DemoIntegration:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
      ApiId: !Ref DemoHttpApi
      Description: Lambda proxy integration
      IntegrationType: AWS_PROXY
      IntegrationMethod: POST
      PayloadFormatVersion: "2.0"
      IntegrationUri: !Sub 'arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DemoFunction.Arn}/invocations'

  DemoApiRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
      ApiId: !Ref DemoHttpApi
      RouteKey: "GET /demo"
      AuthorizationType: AWS_IAM
      Target: !Join
        - /
        - - integrations
          - !Ref DemoIntegration

```

In my next post, I will be sharing how we can connect a lambda function to an application load balancer.