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:
- Change the event type from
Api
toHttpApi
for each of the lambda objects - API object type from
Serverless::Api
toServerless::HttpApi
- 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, thisServerless::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:
- 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: {}
- 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!
Top comments (2)
@james - shouldn't the "type" of your events also have changed from "Api" to "HttpApi"?
Yes it should, I must have copied that across wrong from my test code - good catch!