Creating an API Gateway with HTTP API

First, congratulations again on learning how to define and deploy your first serverless application!

But that's not enough for your client, the "Sauf Pompiers" folks. They also want a functional API with which they can interact, not just three isolated Lambdas in a CloudFormation stack. We can't expect them to manually invoke them, we need to expose their functionality through an API. And this requires us to use the AWS API Gateway. This section will connect on your previous work and we will create together an API that exposes an HTTP interface to all of your previous three Lambda function.

As we briefly touched before, AWS Lambda is an isolated permissionless function. Completely locked down, without any external way to access it. It doesn't run at all, unless its triggered by an event. Those events can come from various other services, such as S3 Buckets, API Gateway, AppSync GraphQL, Alexa, and many more.

So how do we create an API with AWS Lambda?

AWS API Gateway

As you could presume, API Gateway is a completely separate service from AWS Lambda. It's purpose is only to define endpoints and provide external access to HTTP requests with their appropriate response formatting, security, rate limiting, and so on. If you want to get more specific on the API Gateway, please take a look at it's Documentation

There are multiple ways of how to define an API Gateway, as a :

  • separate template resource, NO Swagger
  • separate template resource, WITH Swagger
  • through an AWS Lambda Event trigger

Here are the definition examples

Separate API template resource NO Swagger

BasicAWSApiGateway:
  Type: AWS::Serverless::Api
  Properties:
    Name: Basic AWS Api Gateway
    StageName: Stage

Separate API template resource WITH Swagger

Here is the example with the Swagger.

  GetOneApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: prod
      DefinitionBody:
        swagger: 2.0
        info:
          title:
            Ref: AWS::StackName
        paths:
          /someitems/{id}:
            get:
              parameters:
              - name: id
                in: path
                required: true
                type: string
              responses: {}
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetOneLambda.Arn}/invocations
  GetOneLambda:
    Type: AWS::Serverless::Function
    ...
      Events:
        Api:
          Type: Api
          Properties:
            Path: /someitems/{id}
            Method: GET
            RestApiId: !Ref GetOneApi

Looks good, but its a bit too verbose, right?

AWS Lambda Event trigger

Here comes a SAM abstracted example for a Serverless Function:

YourSAMLambdaFunction
  Type: AWS::Serverless::Function
  Properties:
    Runtime: nodejs12.x
    CodeUri: src/
    Handler: index.handler
    Events:
      YourAPIEndpointName:
        Type: API
        Properties:
          Path: /hello
          Method: GET
          RestApiId: !Ref HelloApi ## This is optional.

As you could notice, a lot simpler, but without any configuration for CORS, Stage, and so forth. Recommended for same origin domains. Tthis example is basically just adding an Event Trigger, which automatically creates the whole resource and the endpoints underneath.

The RestApiId property points to the separate API resource you defined above.

Task

Within your SAM template, create three API GW endpoints for your Lambdas.

  1. The enter-expense Lambda should be a POST HTTP endpoint, which requires the following parameters:
    • issuer,
    • date,
    • description,
    • amount,
    • currency
  2. The list-expenses Lambda should be a GET HTTP endpoint, it doesn't require any parameter.
  3. The update-expense Lambda should be a PUT HTTP endpoint in the format /expenses/{expenseId}, which requires the following parameters:
    • expenseId
    • issuer,
    • date,
    • description,
    • amount,
    • currency
  4. Deploy it using SAM CLI
  5. Try the code from the UI

Hints

  1. You don't have to define parameters in the Swagger for it, just add Events as a property to your Lambda Function properties.

  2. Quite identical to the first solution.

  3. The main difference for the update-expense Lambda Function is that you need to pass a parameter for the expenseId in the path, while the rest go through the HTTP body.

Additional Help

Only use this if you've spent more than 10 minutes on a single task item.

1. Enter Expense API
  ExpensesApi:
    Type: AWS::Serverless::Api

  ...

  EnterExpense:
    Type: AWS::Serverless::Function
    Properties:
    ...
      Events:
        SaveApi:
          Type: Api
          Properties:
            Path: /save
            Method: POST
            RestApiId: !Ref ExpensesApi
3. Update Expense API
  ExpensesApi:
    Type: AWS::Serverless::Api
    ...
    Properties:
      ...
      DefinitionBody:
        swagger: 2.0
        info:
          title:
            Ref: AWS::StackName
        paths:
          /expenses/{id}:
            put:
              parameters:
              - name: id
                in: path
                required: true
                type: string
              responses: {}
              x-amazon-apigateway-integration:
                httpMethod: POST
                type: aws_proxy
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${UpdateExpenseLambda.Arn}/invocations
  UpdateExpenseLambda:
    Type: AWS::Serverless::Function
    Properties:
      Handler: update-expense.handler
      Runtime: nodejs12.x
      Events:
        Api:
          Type: Api
          Properties:
            Path: /expenses/{id}
            Method: PUT
            RestApiId: !Ref ExpensesApi

results matching ""

    No results matching ""