Connecting Lambda to API Gateway
The Lambda exists, the routes exist, but they don't talk to each other yet.
What you'll learn
- How API Gateway Methods work
- Connecting a route to a Lambda function
- Lambda permissions for API Gateway
- Deployment and Stage resources
We have a Lambda function and we have API Gateway routes. But right now they're just sitting there, not talking to each other. The missing piece is the Method resource, this is what connects an HTTP method on a route to a specific Lambda function.
Method resource
A Method tells API Gateway: "When someone sends a GET request to /hello, forward it to this Lambda function." Add this under your Lambda definition:
> # Lambda
...
# Methods
GetHelloMethod:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref RustExample
ResourceId: !Ref HelloResource
AuthorizationType: NONE
HttpMethod: GET
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Sub "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloFunction.Arn}/invocations"Let me explain the important parts:
ResourceId: !Ref HelloResource- This points to the/helloroute we created in the configuration lesson. The!Reffunction grabs the ID of that resource.AuthorizationType: NONE- No authentication required. Anyone can call this endpoint. We'll add auth in a real project, but for learning, this is fine.HttpMethod: GET- This method only responds to GET requests.Type: AWS_PROXY- This is the important one. It tells API Gateway to forward the entire HTTP request to your Lambda as a JSON object. That's why we useApiGatewayProxyRequestin our Rust code.IntegrationHttpMethod: POST- Yes, this is alwaysPOSTeven though our API method isGET. This is the method API Gateway uses to invoke the Lambda, not the method your client uses.Uri- The ARN of the Lambda function. That long string is just the AWS way of saying "this Lambda function right here."
Warning
IntegrationHttpMethod is always POST for Lambda integrations. This is not a typo. API Gateway invokes Lambda functions using a POST request internally, regardless of what HTTP method the client used.
Lambda permissions
Just because API Gateway knows about your Lambda doesn't mean it's allowed to invoke it. AWS is very strict about permissions. You need to explicitly grant API Gateway permission to call your function:
> # Methods
...
# Permissions
HelloFunctionApiPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref HelloFunction
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
SourceArn: !Sub "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${RustExample}/*"The SourceArn uses a wildcard (/*) at the end, which means any method on any route of this API Gateway can invoke the function. This is fine for our tutorial. In production, you'd make this more specific.
Deployment and Stage
Here's something that always trips me up: even after defining everything, your API won't be accessible until you create a Deployment and a Stage. Think of it like this - the Deployment is a snapshot of your API configuration, and the Stage is the environment (like dev or prod) where that snapshot is published.
> # Permissions
...
# Deployment
ApiDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn:
- GetHelloMethod
Properties:
RestApiId: !Ref RustExample
ApiStage:
Type: AWS::ApiGateway::Stage
Properties:
RestApiId: !Ref RustExample
DeploymentId: !Ref ApiDeployment
StageName: !Ref StageNameThe
DependsOnis important. It tells CloudFormation to wait until the Method is created before creating the Deployment. Without this, the deployment might happen before the methods exist, and you'll get an empty API.
Outputs
Finally, let's add an Outputs section so we can easily find our API URL after deploying:
Outputs:
ApiUrl:
Description: API Gateway endpoint URL
Value: !Sub "https://${RustExample}.execute-api.${AWS::Region}.amazonaws.com/${StageName}"
HelloFunctionArn:
Description: Hello Lambda Function ARN
Value: !GetAtt HelloFunction.ArnAfter deployment, SAM will print these values in the terminal so you know exactly where your API is.
Here's how all the pieces connect now:
Client → GET /hello
→ API Gateway (RustExample)
→ Route (HelloResource: /hello)
→ Method (GetHelloMethod: GET)
→ Integration (AWS_PROXY)
→ Lambda (HelloFunction)
→ Your Rust handler
→ ApiGatewayProxyResponse
Every layer in that chain is something we defined in template.yaml. If any piece is missing, the request won't make it to your code.
Everything is wired up. In the next post, we'll actually build and deploy this to AWS and test it with a real HTTP request.