AWS Lambda返回数据不符合规范导致CloudFront报502错误排查求助
我最近写了人生第一个Lambda脚本,是个简单的HTTP转邮件网关。现在遇到个头疼的问题:当Lambda解析请求并生成邮件的时候,前端通过CloudFront访问会收到502错误,错误提示是:
The Lambda function returned an invalid entry in the headers object: Each header entry in the headers object must be an array. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
我的Lambda处理函数是这样写的,我只是把传入的event对象做了装饰后返回:
def lambda_handler(event, context): returnAddr=do_clever_stuff(event) response = { "headers": { "location": [ { "key": "Location", "value": returnAddr } ] }, "status": 303, "statusDescription": "See Other" } event['Records'][0]['cf']['response']=response return event
我在Lambda测试控制台里看到的完整返回数据如下:
{ "Records": [ { "cf": { "config": { "distributionDomainName": "redacted.cloudfront.net", "distributionId": "EDFDVBD6EXAMPLE", "eventType": "origin-request", "requestId": "4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ==" }, "request": { "clientIp": "203.0.113.178", "headers": { "x-forwarded-for": [ { "key": "X-Forwarded-For", "value": "203.0.113.178" } ], "user-agent": [ { "key": "User-Agent", "value": "Amazon CloudFront" } ], "via": [ { "key": "Via", "value": "2.0 2afae0d44e2540f472c0635ab62c232b.cloudfront.net (CloudFront)" } ], "host": [ { "key": "Host", "value": "example.org" } ], "cache-control": [ { "key": "Cache-Control", "value": "no-cache" } ] }, "method": "POST", "origin": { "custom": { "customHeaders": {}, "domainName": "example.org", "keepaliveTimeout": 5, "path": "", "port": 443, "protocol": "https", "readTimeout": 30, "sslProtocols": [ "TLSv1", "TLSv1.1", "TLSv1.2" ] } }, "querystring": "", "uri": "/", "body": { "data": "<<redacted>>" } }, "response": { "headers": { "location": [ { "key": "Location", "value": "/" } ] }, "status": 303, "statusDescription": "See Other" } } } ] }
我感觉自己的response格式是符合要求的啊,到底哪里错了?后来我看AWS文档里的其他示例,发现人家不是返回装饰后的event对象,而是直接返回response,但我改成直接return response之后,还是报同样的502错误,这就更懵了。
问题排查与解决方案
兄弟,你这是踩了CloudFront Lambda@Edge响应格式的两个隐藏坑了!我给你拆解清楚:
1. 响应headers的格式和请求headers不一样!
你现在写的headers格式是请求对象里的结构(每个header是包含key和value的对象数组),但CloudFront要求响应对象的headers是另一种格式:键为小写的header名称,值直接是字符串数组,不需要嵌套key-value对象。
2. Status字段必须是字符串类型!
你写的status: 303是整数,但CloudFront明确要求响应的status字段必须是字符串类型,这个细节很容易忽略。
修正后的代码示例
把你的response改成下面这样,然后直接return这个response对象就行(origin-request触发器直接返回响应不需要修改event):
def lambda_handler(event, context): returnAddr = do_clever_stuff(event) # 注意这里的格式变化 response = { "headers": { "location": [returnAddr] # 直接放字符串数组,去掉key-value嵌套 }, "status": "303", # 改成字符串类型 "statusDescription": "See Other" } # 不需要修改event,直接返回response return response
为什么之前改return response没用?
因为你只是改了返回的对象,但没修正headers格式和status类型这两个核心问题,所以CloudFront还是会报格式错误。现在把这两点都改了,应该就能解决502的问题了。
备注:内容来源于stack exchange,提问作者symcbean




