I start study AWS serverless using lambda and API Getway, So I was thinking to create a REST API for a sample project. I noticed that in API Getway, we only can create the http methods which can trigger lambda functions, So I'm not sure if I get this right but, do we need one lambda function for each api route? or we can handle it somehow using one lambda function.
For example, lets say my project need api for below list :
Login
Register
GetUserData
Then if I going to make this by using API Getway and Lambda, I need to have 3 Lambda functions?
Like if I want create API for those mentioned above, it should be something like this for the endpoints ?
https://API_GETWAY_DOMAIN/STAGE/LAMBDA_FUNCTION_FOR_LOGIN
https://API_GETWAY_DOMAIN/STAGE/LAMBDA_FUNCTION_FOR_REGISTER
https://API_GETWAY_DOMAIN/STAGE/LAMBDA_FUNCTION_FOR_GET_USER_DATA
And is there any way to send multi http request to one lambda function, and handle each one of them inside the lambda?
It is possible to have multiple API Gateway routes direct to the same Lambda function. How to set that up depends on how you're maintaining your infrastructure.
For example, if you're using CloudFormation with the Serverless Application Model (SAM), which I recommend since it's probably the most straightforward way to keep track of serverless infrastructure (and infrastructure as code = awesome), you would define your AWS::Serverless::Function with a separate API Gateway source event for each route you define in your AWS::Serverless::Api.
Something like the following:
YourApi:
Type: AWS::Serverless::Api
Properties:
...
DefinitionBody:
swagger: 2.0
...
paths:
'/Login':
post:
x-amazon-apigateway-integration:
# APIG->Lambda requests are always POST
httpMethod: post
type: aws_proxy
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${YourLambda.Arn}/invocations
'/Register':
post:
x-amazon-apigateway-integration:
# APIG->Lambda requests are always POST
httpMethod: post
type: aws_proxy
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${YourLambda.Arn}/invocations
'/GetUserData':
get:
x-amazon-apigateway-integration:
# APIG->Lambda requests are always POST
httpMethod: post
type: aws_proxy
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${YourLambda.Arn}/invocations
YourLambda:
Type: AWS::Serverless::Function
Properties:
...
Events:
login:
Type: Api
Properties:
Path: '/Login'
Method: post
RestApiId: {Ref: YourApi}
register:
Type: Api
Properties:
Path: '/Register'
Method: post
RestApiId: {Ref: YourApi}
getUserData:
Type: Api
Properties:
Path: '/GetUserData'
Method: get
RestApiId: {Ref: YourApi}
Keep in mind, though, that there are pros and cons to consolidating routes into one Lambda function. This StackOverflow question/answer explores that, but I'd like to add a few more benefits to separated Lambda functions:
Clearer metrics on how often your routes are getting called - You get invocations/errors/etc. metrics in CloudWatch for each Lambda function out-of-the-box, so separating them can make it easy to see how often people are registering versus logging in, etc.
More granular alarming - You can set different latency/error/etc. thresholds for different routes, and if an alarm goes off, you know exactly which Lambda function it's for.
Related
Is there a way to do this?
My use case
I'm trying to integrate API gateway and SNS, but every guide/tutorial I found get the TopicArn from the gateway incoming requeste, i.e. from the user call, but since my endpoint will push to a single topic I want to avoid this step, having the API gateway adding it (hardcoded) to the integration request.
AFAIK the only way to do this is via mapping template, is that right?
It was easy and probably I was making some typos at the beginning, so that's why I wasn't succeeding.
AWS::ApiGateway::Method Integration property docs
Amazon API Gateway API request and response data mapping reference
Cloudformation template relevant code
Resources:
ApiGatewayMethod:
Type: AWS::ApiGateway::Method
Properties:
Integration:
RequestParameters:
integration.request.querystring.<query-param-name>:
IntegrationResponses:
- StatusCode: '200'<desired value>
MethodResponses:
- StatusCode: '200'
ResponseModels:
application/json: "Empty"
I am trying to deploy the api and lambda function using SAM. But the Method Response and Integration Response are empty. I am aiming to configure the api-gateway like below picture. In this I have manually configured the api-gateway and its working but when I use the SAM to generate the api-gateway it doesn't shpes the Method Response and Integration Response.
Without Sam:
With Sam:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Timeout: 500
MemorySize: 5000
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
GatewayResponses:
DEFAULT_4xx:
ResponseParameters:
Headers:
Access-Control-Expose-Headers: "'WWW-Authenticate'"
Access-Control-Allow-Origin: "'*'"
InferenceFunction:
Type: AWS::Serverless::Function
Properties:
PackageType: Image
Events:
Inference:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /zero-shot-classification
Method: post
RestApiId: !Ref MyApi
Metadata:
Dockerfile: Dockerfile
DockerContext: ./zero-shot-classification
DockerTag: zero-shot-classification
The difference you see is the difference between how the payload is sent to the lambda and how API gateway processes the response from the lambda. Seeing as in your CloudFormation you do not specify a specification for your API endpoints, AWS SAM will construct this based on the events from your functions. However, AWS SAM will always use the LAMBDA_PROXY integration type, while you seem to be wanting to use the LAMBDA integration type.
I'd suggest you take your manually created API gateway and export it to an openapi/swagger definition. This can then be used as DefinitionBody in you MyApi. That way you can specify it uses the LAMBDA integration instead of the LAMBDA_PROXY integration. Don't forget to update the swagger definition so it uses the created function in your cloudformation and not the function that existed when you exported the API.
That being said, the LAMBDA_PROXY way is more widely used and also removes the need for template mappings in your API Gateway. It is also the only integration type for lambdas that is supported in the HTTP API (API Gateway v2), which is a lot cheaper than the classic REST API.
I'm trying to work my way through AWS sam and setting up a new ApiGateway. I want the lambdas to run without the 'use lambda proxy integration' setting. I've been trying for ages now, and haven't made much progress.
A simplified version of my template.yaml
Resources:
MyLambda:
Type: AWS::Serverless::Function
Properties:
#snip#
Events:
PostEvent:
Type: Api
Properties:
Path: /Some/Path
Method: Post
RestApiId:
Ref: MyApi
MyApi:
Type: AWS::Serverless::Api
Properties:
Name: Some-Api
StageName: Prod
As you can see, I haven't made any progress at all. I'm simply getting lost in the configuration here, and hoping that anyone can point me in the right direction
Sicne you have opted out of integration proxy, the request and response may need mapping.
Have you tried updating the integration response - mapping template, try below,
AWS::Serverless::Api
GatewayResponses
I've been using AWS SAM for a websocket API and that's been working well. Today, I needed to add an HTTPS API, however my attempt to do so results in a new API gateway, under a different subdomain, to be created. I'd like them to share the same domain, so users only need to change the protocol (from HTTPS to WSS).
This is a relevant section of my template.yaml:
# This seems to implicitly create and use a `ServerlessRestApi` API gateway
PingLambda:
Type: AWS::Serverless::Function
Properties:
CodeUri: lambda/
Handler: app.pingHandler
Runtime: nodejs12.x
Events:
Ping:
Type: Api
Properties:
Path: /ping
Method: get
# I use this for the various websocket lambdas, works like a charm
WebSocketApi:
Type: AWS::ApiGatewayV2::Api
Properties:
Name: SimpleRelayWebSocket
ProtocolType: WEBSOCKET
RouteSelectionExpression: \\$default
# ...
# I'd love both of these to use the same subdomain/API gateway setup
Outputs:
APIURL:
Description: URL of the Simple Relay HTTPS API
Value: !Sub 'https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/${Stage}'
WebSocketURL:
Description: URL of the Simple Relay WSS API
Value: !Sub 'wss://${WebSocketApi}.execute-api.${AWS::Region}.amazonaws.com/${Stage}'
I'm not sure how to proceed, considering the WebSocketApi has ProtocolType: WEBSOCKET set there. Is there some way to split the API into multiple things with different protocols, or is there something else I'm missing?
I need to do the same thing. One possible solution is to put both behind a CloudFront distribution. I'll do this probably, since I'm already using CloudFront to serve the front-end from S3, and some back-end endpoints.
I am trying to figure out the correct definition for my aws sam template for calling a state machine from an api proxy request. Can this be done using AWS::Serverless::Api and a swagger definition? I have this call now that goes to a lambda and Id like to replace it with my state machine
paths:
"/{userUd}":
any:
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${userFunction.Arn}/invocations
responses: {}
Or must I use the RestAPI gateway model? And if so an example would be amazing as I am having difficulty finding any.