Flutter Firebase云函数代理CORS配置错误,请求头不被允许如何解决?
解决Firebase云函数代理的CORS配置问题
你的错误根源是向目标API发送请求时错误携带了CORS响应头,同时预检请求的配置也存在语法和内容错误。以下是具体修正步骤:
错误点分析
- OPTIONS预检响应错误:
Access-Control-Allow-Methods里混入了authorization(这是请求头字段,不是HTTP请求方法),导致预检校验不通过;- 代码中
res.set('Access-Control-Allow-Origin','*'),多了一个逗号,属于语法错误。
- 向目标API发起请求的冗余头:
Access-Control-Allow-Origin、Access-Control-Allow-Credentials这类头是服务端返回给前端的响应头,不是代理发给目标API的请求头,完全不需要携带。 - 响应处理逻辑错误:
- 重复调用
res.status()会导致响应异常; fetch的响应对象没有直接的data属性,需要先调用json()或text()解析;- 代码里的
response变量未定义,属于笔误。
- 重复调用
- CORS中间件与手动OPTIONS处理冲突:
已经手动处理了OPTIONS请求,再使用cors中间件会造成逻辑重复,建议二选一。
修正后的完整代码
const functions = require('firebase-functions'); exports.proxyAnafAPI = functions.https.onRequest((req, res) => { const apiUrl = 'https://webservicesp.anaf.ro/PlatitorTvaRest/api/v8/ws/tva' + req.url; // 处理OPTIONS预检请求 if (req.method === 'OPTIONS') { res.set('Access-Control-Allow-Origin', '*'); res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, HEAD, OPTIONS'); res.set('Access-Control-Allow-Headers', 'Content-Type, Authorization'); // 前端实际发送的自定义头都要列在这里 res.set('Access-Control-Max-Age', '3600'); return res.status(200).send(''); } // 处理实际请求 fetch(apiUrl, { method: req.method, headers: { 'Content-Type': 'application/json', // 仅携带目标API需要的请求头,比如前端传了Authorization就转发 ...(req.headers.authorization && { 'Authorization': req.headers.authorization }) }, body: req.method !== 'GET' ? JSON.stringify(req.body) : undefined // GET请求不要带body }) .then(async apiRes => { // 给前端返回CORS响应头 res.set('Access-Control-Allow-Origin', '*'); res.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, HEAD, OPTIONS'); res.set('Access-Control-Allow-Headers', 'Content-Type, Authorization'); // 解析目标API响应并返回给前端 const responseBody = await apiRes.json(); return res.status(apiRes.status).json(responseBody); }) .catch(error => { console.error('代理请求出错:', error); res.status(500).send('代理请求失败'); }); });
关键说明
- 仅在云函数返回给前端的响应中设置CORS头,向目标API发请求时只带目标API要求的头;
- OPTIONS预检的
Access-Control-Allow-Headers必须包含前端实际会发送的所有自定义请求头; - 避免手动处理OPTIONS和cors中间件同时使用,防止逻辑冲突;
- fetch响应必须通过
json()/text()方法解析后才能获取内容。
内容的提问来源于stack exchange,提问作者Roberto
相关产品推荐
相关产品推荐

