使用Fetch API无法获取CloudFront返回的自定义请求头问题
问题描述
我在Flask服务器上接收CloudFront返回的自定义请求头,想提取该头的值并展示在页面上。已经在两端完成CORS配置,响应头包含Access-control-allow-origin: *。
现在的问题是:点击调用CloudFront函数的按钮会触发多个网络请求,但用Fetch API无法获取包含所需自定义头的请求的响应头。
相关代码
1. 前端HTML中的JavaScript代码
<script> function fibonacci() { var n = document.getElementById('fibCFInput').value; console.log("testing.." + n) //fetch('/fibonacci/' + n) //NOTE: neither fetch command has worked for me. fetch("<cloudfront url>/fibonacci/" + n) .then(response => { response.headers.forEach((value, name) => { console.log(`${name}: ${value}`); }); const fibval = response.headers.get("Fibval"); console.log(`fibval value: ${fibval}`); }) } </script>
2. Flask路由代码
@app.route("/fibonacci/<int:value>", methods=['GET', 'OPTIONS']) def fibonacci(value): url = f"<cloudfront url>/fibonacci/{value}" return redirect(url, code=302)
3. CloudFront函数代码
import cf from 'cloudfront'; async function handler(event) { const url = event.request; const pathSegments = url.uri.split('/') console.log(pathSegments) const key = pathSegments[2] //returns fib number from input console.log(key) var result = fibFunc(parseInt(key)) const mainweburl = "http://fakeURL.com:portnumber/" const all = "*" var response = { statusCode: 302, statusDescription: 'Found', headers: { 'access-control-allow-origin': {"value": all}, "location": { "value": mainweburl}, 'fibval': {'value': result.toString()}, } }; return response; }
试过多种打印方式和变量调整,也核对过CORS文档,但问题仍未解决。出于性能要求,不能使用XMLHttpRequest(会重复发送请求影响性能指标)。
解决方法
问题根源
- Fetch默认自动跟随重定向:CloudFront返回的是302重定向响应,Fetch默认会自动跳转到
Location指定的地址,此时你获取到的是最终跳转页面的响应,而非CloudFront带fibval头的302响应。 - 自定义头未暴露给前端:CORS规范中,自定义响应头默认无法被前端JavaScript访问,必须通过
Access-Control-Expose-Headers显式声明。
修改步骤
1. 调整前端Fetch配置
添加redirect: 'manual'选项,阻止自动跳转,直接捕获CloudFront的302响应:
function fibonacci() { var n = document.getElementById('fibCFInput').value; console.log("testing.." + n) fetch("<cloudfront url>/fibonacci/" + n, { redirect: 'manual' // 关键:不自动跟随重定向 }) .then(response => { // 现在能拿到CloudFront返回的302响应 response.headers.forEach((value, name) => { console.log(`${name}: ${value}`); }); // HTTP头不区分大小写,Fetch返回的头名统一为小写 const fibval = response.headers.get("fibval"); console.log(`fibval value: ${fibval}`); // 若需跳转到目标页面,手动处理 const location = response.headers.get('location'); if (location) { window.location.href = location; } }) }
2. 更新CloudFront函数响应头
添加Access-Control-Expose-Headers,将fibval头暴露给前端:
import cf from 'cloudfront'; async function handler(event) { const url = event.request; const pathSegments = url.uri.split('/') console.log(pathSegments) const key = pathSegments[2] //returns fib number from input console.log(key) var result = fibFunc(parseInt(key)) const mainweburl = "http://fakeURL.com:portnumber/" const all = "*" var response = { statusCode: 302, statusDescription: 'Found', headers: { 'access-control-allow-origin': {"value": all}, // 添加此行,暴露自定义fibval头 'access-control-expose-headers': {"value": "fibval"}, "location": { "value": mainweburl}, 'fibval': {'value': result.toString()}, } }; return response; }
额外说明
- 若不需要跳转页面,可移除手动跳转的代码;若需要保留跳转逻辑,手动调用
window.location.href不会额外增加性能开销,和自动跳转效果一致。 - HTTP头名称不区分大小写,但Fetch API返回的头字段会统一转为小写,因此用
response.headers.get("fibval")更稳妥(原代码的"Fibval"也能生效)。
内容的提问来源于stack exchange,提问作者Zer0
相关产品推荐
相关产品推荐

