为何AWS API Gateway在HTTP/1.1下不向Lambda传递Origin头?
问题:AWS API Gateway在HTTP/1.1下不传递Origin头的原因与解决方法
该问题仅在使用HTTP/1.1时出现,HTTP/2下无此异常。
现有一个AWS Node.js 18 Lambda,代码如下:
export const healthHandler = async (event) => { return { body: `ok! origin: '${event.headers['origin']}'` } }
通过Serverless部署至AWS API Gateway,配置如下:
service: gateway-cors provider: name: aws stage: test runtime: nodejs18.x functions: health: handler: index.healthHandler events: - http: method: GET path: health/{any+} cors: true
使用HTTP/2发起请求时,结果如下:
curl https://<id>.execute-api.eu-west-1.amazonaws.com/test/health/test -H "Origin: https://test.com" --http2 ok! origin: 'https://test.com'
但使用HTTP/1.1发起请求时,结果为:
curl https://<id>.execute-api.eu-west-1.amazonaws.com/test/health/test -H "Origin: https://test.com" --http1.1 ok! origin: 'undefined'
请问为何AWS API Gateway在HTTP/1.1下不传递Origin头,如何使其正常传递?
原因分析
AWS API Gateway对HTTP/1.1和HTTP/2的请求头处理逻辑存在差异:
- HTTP/2协议强制要求请求头名称为小写,API Gateway会自动将所有请求头转换为小写,因此代码中通过
event.headers['origin']能正常获取值。 - HTTP/1.1无强制小写要求,API Gateway会保留请求头的原始大小写(浏览器发送的Origin头通常为首字母大写的
Origin),但代码中仅查找小写的origin键,无法匹配到对应值,最终返回undefined。
另外,配置cors: true仅让API Gateway自动处理CORS响应头,不会修改请求头的大小写,这就导致了两种HTTP版本下的行为差异。
解决方法
方法一:兼容大小写获取请求头
修改Lambda代码,同时检查大小写的Origin和origin,或统一转换为小写后查找,确保两种场景都能拿到值:
export const healthHandler = async (event) => { // 简单兼容:同时匹配大小写键 const origin = event.headers['Origin'] || event.headers['origin']; return { body: `ok! origin: '${origin}'` } }
如果需要更严谨的实现,可以遍历headers对象,忽略大小写匹配:
export const healthHandler = async (event) => { let origin; for (const key in event.headers) { if (key.toLowerCase() === 'origin') { origin = event.headers[key]; break; } } return { body: `ok! origin: '${origin}'` } }
方法二:通过API Gateway配置统一请求头大小写
在Serverless配置中添加映射模板,强制将所有请求头转换为小写,这样无论使用哪种HTTP版本,代码都能通过小写键获取值:
service: gateway-cors provider: name: aws stage: test runtime: nodejs18.x functions: health: handler: index.healthHandler events: - http: method: GET path: health/{any+} cors: true requestParameters: - method.request.header.origin: true requestTemplates: application/json: | { "headers": { #foreach($header in $input.params().header.keySet()) "$header.toLowerCase()": "$input.params().header.get($header)" #if($foreach.hasNext),#end #end } }
注意:该方式仅适用于REST API类型的API Gateway,需启用映射模板功能。
内容的提问来源于stack exchange,提问作者Zaz
相关产品推荐
相关产品推荐

