使用Terraform部署AWS API Gateway与Lambda时遇路由及调用错误
问题排查:AWS API Gateway + Terraform部署异常
问题现象
1. API Gateway调用返回404
Cloud9中执行curl命令:
curl -X "PUT" -H "Content-Type: application/json" -d "{ \"id\": \"abcdef234\", \"price\": 12345, \"name\": \"myitem\" }" $INVOKE_URL/items
返回结果:
{"message":"Not Found"}
2. Lambda直接调用返回400错误
执行命令:
aws lambda invoke --region=us-east-1 --function-name=$(terraform output -raw function_name) response.json
终端返回:
{ "StatusCode": 200, "ExecutedVersion": "$LATEST" }
但response.json内容:
{"statusCode":400,"body":"\"Unsupported route: \\\"undefined\\\"\"","headers":{"Content-Type":"application/json"}}
相关代码
Lambda函数代码
const AWS = require("aws-sdk"); const dynamo = new AWS.DynamoDB.DocumentClient(); exports.handler = async (event, context) => { let body; let statusCode = 200; const headers = { "Content-Type": "application/json" }; try { switch (event.routeKey) { case "DELETE /items/{id}": await dynamo .delete({ TableName: "http-crud-tutorial-items", Key: { id: event.pathParameters.id } }) .promise(); body = `Deleted item ${event.pathParameters.id}`; break; case "GET /items/{id}": body = await dynamo .get({ TableName: "http-crud-tutorial-items", Key: { id: event.pathParameters.id } }) .promise(); break; case "GET /items": body = await dynamo.scan({ TableName: "http-crud-tutorial-items" }).promise(); break; case "PUT /items": let requestJSON = JSON.parse(event.body); await dynamo .put({ TableName: "http-crud-tutorial-items", Item: { id: requestJSON.id, price: requestJSON.price, name: requestJSON.name } }) .promise(); body = `Put item ${requestJSON.id}`; break; default: throw new Error(`Unsupported route: \"${event.routeKey}\"`); } } catch (err) { statusCode = 400; body = err.message; } finally { body = JSON.stringify(body); } return { statusCode, body, headers }; };
Terraform API Gateway配置
resource "aws_apigatewayv2_route" "crud_api_route1" { api_id = aws_apigatewayv2_api.crud_api.id route_key = "GET /items/{id}" target = "integrations/${aws_apigatewayv2_integration.crud_integration.id}" } resource "aws_apigatewayv2_route" "crud_api_route2" { api_id = aws_apigatewayv2_api.crud_api.id route_key = "GET /items" target = "integrations/${aws_apigatewayv2_integration.crud_integration.id}" } resource "aws_apigatewayv2_route" "crud_api_route" { api_id = aws_apigatewayv2_api.crud_api.id route_key = "PUT /items" target = "integrations/${aws_apigatewayv2_integration.crud_integration.id}" } resource "aws_apigatewayv2_route" "crud_api_route3" { api_id = aws_apigatewayv2_api.crud_api.id route_key = "DELETE /items/{id}" target = "integrations/${aws_apigatewayv2_integration.crud_integration.id}" } resource "aws_apigatewayv2_integration" "crud_integration" { api_id = aws_apigatewayv2_api.crud_api.id integration_type = "HTTP_PROXY" integration_method = "POST" integration_uri = "https://a7fpzomc93.execute-api.us-west-1.amazonaws.com" } resource "aws_lambda_permission" "api_gw" { statement_id = "AllowExecutionFromAPIGateway" action = "lambda:InvokeFunction" function_name = aws_lambda_function.http-crud-tutorial-function.function_name principal = "apigateway.amazonaws.com" source_arn = "${aws_apigatewayv2_api.crud_api.execution_arn}/*/*" }
核心问题与修复方案
API Gateway集成类型错误
当前使用HTTP_PROXY类型,集成Lambda需改为AWS_PROXY,且integration_uri必须指向Lambda的Invoke ARN,而非固定API地址。缺失API Gateway部署与阶段
未创建aws_apigatewayv2_deployment和aws_apigatewayv2_stage资源,导致配置的路由未生效,引发404错误。Lambda直接调用无Event参数
用aws lambda invoke直接调用时未传入模拟的API Gateway事件,event.routeKey为undefined导致400,属于正常现象,需通过API Gateway触发或传入模拟Event测试。
修改后的Terraform集成与部署配置示例
# 修正Lambda集成配置 resource "aws_apigatewayv2_integration" "crud_integration" { api_id = aws_apigatewayv2_api.crud_api.id integration_type = "AWS_PROXY" integration_method = "POST" integration_uri = aws_lambda_function.http-crud-tutorial-function.invoke_arn } # 新增部署资源,路由变更时自动重新部署 resource "aws_apigatewayv2_deployment" "crud_deployment" { api_id = aws_apigatewayv2_api.crud_api.id triggers = { redeployment = sha1(jsonencode([ aws_apigatewayv2_route.crud_api_route, aws_apigatewayv2_route.crud_api_route1, aws_apigatewayv2_route.crud_api_route2, aws_apigatewayv2_route.crud_api_route3, aws_apigatewayv2_integration.crud_integration ])) } lifecycle { create_before_destroy = true } } # 新增阶段资源,对外提供访问入口 resource "aws_apigatewayv2_stage" "crud_stage" { api_id = aws_apigatewayv2_api.crud_api.id name = "prod" deployment_id = aws_apigatewayv2_deployment.crud_deployment.id }
内容的提问来源于stack exchange,提问作者killydev767
相关产品推荐
相关产品推荐

