DEV Community

loading...

How to use the new AWS HTTP API with SAM

jcts3 profile image James Stratford Updated on ・3 min read

Hi, I'm new to the world of serverless this year, and in my role at Solve I've been working on trying out some of the newest additions to the serverless world announced at this year's AWS re:invent to see if they suit us.

One of these new announcements that we are stoked about is the new HTTP API service. As our new app is to have a number of services driven out of AWS, all you had to say was 'faster' and 'up to 70% cheaper' to get our interest! To test it out we picked a service that was going to be particularly busy, and I've been trying out how to implement it with SAM. It ended up being a non-trivial fix, and there were no docs for multi-endpoint services - so I thought I'd write up what I found!

Previously on our API...

Our old API had a POST and GET endpoint, both to be served by lambda functions which would do call(s) to DynamoDB. The SAM template looked like this:

Resources:
...
  GetOneOfTheThing: 
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.getOneThing
      Events:
        GetOneThing:
          Type: Api
          Properties:
            Path: /getOneThing/{Key}/
            Method: get
            RestApiId: !Ref MyApi

  PostManyKeysForManyThings:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.postGetManyThings
      Events:
        GetVariationDetail:
          Type: Api
          Properties:
            Path: /getManyThings/
            Method: post
            RestApiId: !Ref MyApi  

  MyApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: !Ref Stage
      MethodSettings:
        - ResourcePath: "/*"
          HttpMethod: "*"

Initial Template Changes

Simple steps from the documentation:

  1. Change the event type from Api to HttpApi for each of the lambda objects
  2. API object type from Serverless::Api to Serverless::HttpApi
  3. Remove MethodSettings from the API object. As described in the docs the properties of this object are a lot simpler than the previous one. For a single API endpoint, this Serverless::HttpApi object isn't actually needed when using SAM, as it can work out how to fill in the gaps. However, I found that when you wanted to use the HTTP API with two endpoints, this no longer caused a connection between the Lambdas and the new API.

Subtler Template Changes

The things that caught me out from there were:

  1. I needed a DefinitionBody for the HttpApi object. There was no real guidance for this beyond an example of a root path option, so after some tinkering what I found to work was as follows:
      DefinitionBody:
        info:
          title:
            Ref: AWS::StackName
          version: "1.0"
        openapi: 3.0.1
        paths:
          /getOneThing/{flagKey}:
            get:
              responses: {}
          /getManyThings:
            post:
              responses: {}
  1. The catch here, was that the path options couldn't end with a /, therefore the lambda events' paths needed to edited to remove the trailing backslash. (i.e. Path: /getOneThing/{flagKey}/->Path: /getOneThing/{flagKey})
  GetOneOfTheThing: 
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.getOneThing
      Events:
        GetOneThing:
          Type: HttpApi
          Properties:
            Path: /getOneThing/{Key}
            Method: get
            RestApiId: !Ref MyApi

  PostManyKeysForManyThings:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.postGetManyThings
      Events:
        GetVariationDetail:
          Type: HttpApi
          Properties:
            Path: /getManyThings
            Method: post
            RestApiId: !Ref MyApi 

Conclusion

And that was it! No changes at all to the lambdas themselves, and only one change to a test, as the sad-path test of no key being provided to the GET was no longer being caught as a 403 by API Gateway was now returning a 400 by the error catching inside the lambda.

Caveat here of course is that HTTP API is still in beta so some of this may be subject to change, but we are looking forward to its benefits nonetheless!

Discussion

pic
Editor guide
Collapse
apemberton profile image
Andy Pemberton

@james - shouldn't the "type" of your events also have changed from "Api" to "HttpApi"?

Collapse
jcts3 profile image
James Stratford Author

Yes it should, I must have copied that across wrong from my test code - good catch!