使用代理集成通过 API Gateway 触发 AWS Lambda
Posted
技术标签:
【中文标题】使用代理集成通过 API Gateway 触发 AWS Lambda【英文标题】:Trigger AWS Lambda through API Gateway using Proxy Integration 【发布时间】:2018-05-04 22:13:03 【问题描述】:我刚刚开始使用 AWS,并在 AWS Lambda 中制作了一个基本计算器,如下所示:
import json
def lambda_handler(event, context):
op1 = event.get('op1',0)
op2 = event.get('op2',0)
operator = event.get('op', None)
if op1 == 0 or op2 == 0 or operator == None:
result = 'Please enter valid input data'
ret_code = 219
else:
if operator in 'add', 'plus', '+':
result = op1 + op2
ret_code = 278
elif operator in 'subtract', 'minus', '-':
result = op1 - op2
ret_code = 278
elif operator in 'multiply', '*':
result = op1 * op2
ret_code = 278
elif operator in 'divide', '/':
result = op1 / op2
ret_code = 278
else:
result = 'Please enter valid operator'
ret_code = 219
return
'isBase64Encoded': False,
'statusCode': ret_code,
'headers': 'Content-Type': 'application/json',
'body': json.dumps(result)
当我使用以下方法测试 Lambda 时,此函数工作正常
"op1": 7,
"op2": 9,
"op": "divide"
然后我在 Amazon API Gateway 中创建了一个 API,并将其配置为使用 Lambda 代理集成,如 API Setup 所示。
但是,现在当我尝试通过 PUT 或 POST 通过与以前相同的输入数据触发 AWS Lambda 时,我收到 219 错误,这意味着数据没有被传递到 Lambda 事件中,而是 Lambda 是使用默认零,给出错误。我从 API Gateway 得到的响应如下:
Execution log for request test-request
Tue Nov 21 12:19:34 UTC 2017 : Starting execution for request: test-invoke-request
Tue Nov 21 12:19:34 UTC 2017 : HTTP Method: PUT, Resource Path: /
Tue Nov 21 12:19:34 UTC 2017 : Method request path:
Tue Nov 21 12:19:34 UTC 2017 : Method request query string:
Tue Nov 21 12:19:34 UTC 2017 : Method request headers:
Tue Nov 21 12:19:34 UTC 2017 : Method request body before transformations:
"op1": 7,
"op2": 9,
"op": "divide"
Tue Nov 21 12:19:34 UTC 2017 : Endpoint request URI: https://lambda.eu-west-2.amazonaws.com/2015-03-31/functions/arn:aws:lambda:eu-west-2:*:function:newCalc/invocations
Tue Nov 21 12:19:34 UTC 2017 : Endpoint request headers: x-amzn-lambda-integration-tag=test-request, Authorization=*, X-Amz-Date=20171121T121934Z, x-amzn-apigateway-api-id=*, X-Amz-Source-Arn=arn:aws:execute-api:eu-west-2:*:wrsio8dvp3/null/PUT/proxy+, Accept=application/json, User-Agent=AmazonAPIGateway_*, X-Amz-Security-Token=*
Tue Nov 21 12:19:34 UTC 2017 : Endpoint request body after transformations: "resource":"/proxy+","path":"/","httpMethod":"PUT","headers":null,"queryStringParameters":null,"pathParameters":null,"stageVariables":null,"requestContext":"path":"/proxy+","accountId":"*","resourceId":"fsamcn","stage":"test-invoke-stage","requestId":"test-invoke-request","identity":"cognitoIdentityPoolId":null,"accountId":"*","cognitoIdentityId":null,"caller":"*","apiKey":"test-invoke-api-key","sourceIp":"test-invoke-source-ip","accessKey":"*","cognitoAuthenticationType":null,"cognitoAuthenticationProvider":null,"userArn":"arn:aws:iam::*:user/*","userAgent":"Apache-HttpClient/4.5.x (Java/1.8.0_144)","user":"*","resourcePath":"/proxy+","httpMethod":"PUT","apiId":"wrsio8dvp3","body":"\n \"op1\": 7,\n \"op2\": 9,\n \"op\": \"divide\"\n","isBase64Encoded":false
Tue Nov 21 12:19:34 UTC 2017 : Sending request to https://lambda.eu-west-2.amazonaws.com/2015-03-31/functions/arn:aws:lambda:eu-west-2:*:function:newCalc/invocations
Tue Nov 21 12:19:34 UTC 2017 : Received response. Integration latency: 287 ms
Tue Nov 21 12:19:34 UTC 2017 : Endpoint response body before transformations: "isBase64Encoded": false, "statusCode": 219, "headers": "Content-Type": "application/json", "body": "\"Please enter valid input data\""
Tue Nov 21 12:19:34 UTC 2017 : Endpoint response headers: x-amzn-Remapped-Content-Length=0, Connection=keep-alive, x-amzn-RequestId=3befcbd6-ceb6-11e7-a4dd-c3db02aba4a2, Content-Length=139, Date=Tue, 21 Nov 2017 12:19:34 GMT, X-Amzn-Trace-Id=root=1-5a1419d6-106413cfbf4bf985d840894f;sampled=0, Content-Type=application/json
Tue Nov 21 12:19:34 UTC 2017 : Method response body after transformations: "Please enter valid input data"
Tue Nov 21 12:19:34 UTC 2017 : Method response headers: X-Amzn-Trace-Id=sampled=0;root=1-5a1419d6-106413cfbf4bf985d840894f, Content-Type=application/json
Tue Nov 21 12:19:34 UTC 2017 : Successfully completed execution
Tue Nov 21 12:19:34 UTC 2017 : Method completed with status: 219
那么,您能否帮我弄清楚我做错了什么 - 以及如何正确格式化我的请求正文以便能够触发 Lambda 函数。
【问题讨论】:
【参考方案1】:您面临的问题来自 api 网关的代理集成。如果您选中此项,则为您的 lambda 提供的输入结构不再是提供给您 PUT 操作的普通负载。
您的事件参数实际上由以下结构组成(在您的日志中,Endpoint request body after transformations
行)
"resource": "/proxy+",
"path": "/",
"httpMethod": "PUT",
"headers": null,
"queryStringParameters": null,
"pathParameters": null,
....
"body": "\n \"op1\": 7,\n \"op2\": 9,\n \"op\": \"divide\"\n",
"isBase64Encoded": false
因此,要访问您的原始事件,您必须解码 event.body
元素。
【讨论】:
将代码更新为首先使用payload = json.loads(event.get('body'))
将 event.body 作为 dict 读取,然后通过 op1 = payload['op1']
读取单个元素以上是关于使用代理集成通过 API Gateway 触发 AWS Lambda的主要内容,如果未能解决你的问题,请参考以下文章
使用代理通过 AWS API Gateway 的 Lambda 错误
如何允许 API Gateway 代理与 Cognito Authorizer 集成以进行 POST 请求?
使用 HTTP 代理访问 AWS API Gateway 中的标头?
AWS API Gateway 仅在使用 SAM 时支持 CORS for OPTIONS(没有 Lambda 代理集成)