如何在 firebase 函数环境中解决 CORS?
Posted
技术标签:
【中文标题】如何在 firebase 函数环境中解决 CORS?【英文标题】:How to solve CORS in firebase functions enviroment? 【发布时间】:2019-03-06 22:09:39 【问题描述】:我遇到了CORS
问题。在我的functions/index.js
我有:
const cors = require('cors')(
origin: true
);
我的端点是https://sis-t.redsys.es:25443/sis/realizarPago
。我需要使用来自客户端的适当参数对此 url 执行 POST
,这是在 firebase 环境之外。我也有允许外部网络的正确计划,但是向与原始地址不同的地址发出请求会触发CORS
问题:
我已经读到您只需要修改标头,但这仅适用于您向自己的服务器发出请求时。当你执行http.onRequest()
时,你可以在函数内部使用中间件,但是当你向外部服务器进行 POST 时会发生什么?
这是执行POST
的axios
函数:
cardPay: function ()
this.cardProcess = true
axios(
method: 'post',
url: 'https://us-central1-cutre-windrider.cloudfunctions.net/cardPay',
data:
verifiedUserLogged: this.userLogged.uid,
cart: this.cartItemList,
finalPrice: this.serverPrice,
deliveryInfo: this.userLogged.deliveryAdress,
name: this.userLogged.displayName || false,
email: this.userLogged.email
)
.then(response =>
this.requestData = response
this.redsysRedirect(response.data.data)
)
.catch(console.log)
,
redsysRedirect: function (data)
axios.post('https://sis-t.redsys.es:25443/sis/realizarPago',
'Ds_SignatureVersion': 'HMAC_SHA256_V1',
'Ds_MerchantParameters': data.merchantParameters,
'Ds_Signature': data.signature
).then(console.log).catch(console.log)
这些是服务器端函数:
exports.cardPay = functions.https.onRequest((req, res) =>
return cors(req, res, () =>
const cart = req.body.cart
const user = req.body.verifiedUserLogged
const key = admin.database().ref(`sales/$user`).push().key
processCart(cart).then(result =>
console.info(createPayment(result, key))
return res.json( "data": createPayment(result, key) ).end()
).catch(console.log)
)
)
function processCart(cart)
return new Promise((resolve, reject) =>
Promise.all(cart.map(i => switcher(i)))
.then(prices => resolve(
prices.reduce(
(finalPrice, price) => price + finalPrice, 0)
)).catch(console.log)
);
function switcher(item)
switch (item.destiny)
case 'bookedLessons':
return lessonPrice(item.name, item.index)
case 'bookedRentals':
return rentalPrice(item.id, item.index, item.insurancePurchased, item.insuranceId)
case 'bookedLodgins':
return item.reservationData ? roomPriceWithReservation(item.id, item.quantity, item.persons, item.reservationData) : roomPriceNoReservation(item.id, item.quantity, item.persons)
case 'deliveries':
return productPrice(item.id, item.quantity)
case 'bookedCar':
return carPrice(item.id, item.index)
case 'bookedStorage':
return storagePrice(item.index)
case 'bookedTransportation':
return transportationPrice(item.id, item.index, item.persons, item.roundTrip)
case 'bookedDoublePack':
return doublePack(item.id, item.persons)
case 'bookedTriplePack':
return triplePack(item.id, item.persons)
default:
break
function createPayment(total, orderId)
let redsys = new Redsys();
let mParams =
"DS_MERCHANT_AMOUNT":total.toString(),
"DS_MERCHANT_ORDER":orderId,
"DS_MERCHANT_MERCHANTCODE": "025988262",
// "DS_MERCHANT_MERCHANTCODE":tpvInfo.fucCode,
"DS_MERCHANT_CURRENCY":"978",
// "DS_MERCHANT_CURRENCY":tpvInfo.currency,
"DS_MERCHANT_TRANSACTIONTYPE":"0",
// "DS_MERCHANT_TRANSACTIONTYPE":tpvInfo.transaction_type,
"DS_MERCHANT_TERMINAL": "001",
// "DS_MERCHANT_TERMINAL":tpvInfo.terminal,
"DS_MERCHANT_MERCHANTURL":'http://localhost:8080',
"DS_MERCHANT_URLOK":'http://localhost:8080/home?foo=true',
"DS_MERCHANT_URLKO":'http://localhost:8080/home?foo=false'
;
return signature: redsys.createMerchantSignature(/* tpvInfo.secret */ "sq7HjrUOBfKmC576ILgskD5srU870gJ7", mParams) , merchantParameters: redsys.createMerchantParameters(mParams), raw: mParams;
【问题讨论】:
【参考方案1】:对于将来会遇到这个问题的人(或我未来的自己):
如果您已经使用 cors
包配置了 CORS,并且您认为您配置正确,但在浏览器控制台中仍然出现 CORS 错误,请查看这篇文章:
https://haha.world/firebase-cors/
基本上,这是从 Google Cloud Functions 返回的误导性错误,而实际上该错误在您的代码逻辑中(与 CORS 完全无关)
因此,修复此错误的第一步是检查 Google Cloud Functions 日志(或 Firebase Cloud Functions 日志),以查看您的函数是否因代码中的任何错误而崩溃。然后修复它。
注意:对于没有我上面描述的问题的人,您可以查看其他答案,或查看以下资源:
-
https://expressjs.com/en/resources/middleware/cors.html
https://firebase.google.com/docs/functions/http-events#using_existing_express_apps
【讨论】:
对我来说,问题是我需要重新导出 Google 凭据文件。如果 CORS 之前为您工作过,请忽略此错误并在其他地方查找问题。 在您的 Firebase 日志中注意“未处理的拒绝” 哇。就是这样。函数错误,返回 cors 错误。 绝对正确!就我而言,我使用“Test”字符串调用“test”函数,但遇到了与 CORS 相关的错误。【参考方案2】:在您的 Firebase 函数响应标头中,您可以明确允许所有来源:
exports.handler = ((req, res) =>
res.set( 'Access-Control-Allow-Origin': '*' ).sendStatus(200)
)
或者您可以修改它以仅允许特定来源。这通常是我过去使用 Firebase 函数解决 CORS 问题的方式。
【讨论】:
然后响应 res.json(foo: bar)?因为这会覆盖标题,并导致Can't set headers after they are sent
是的,如果您想发送 json 响应,您可以这样做:res.set( 'Access-Control-Allow-Origin': '*' ).status(200).json(foo: bar)
Access-Control-Allow-Origin': '*' 非常危险,难道没有更安全的方法可以从本地应用程序测试您的功能吗?【参考方案3】:
查看https://cloud.google.com/functions/docs/writing/http#handling_cors_requests。从那个文件 -
exports.corsEnabledFunction = (req, res) =>
// Set CORS headers
// e.g. allow GETs from any origin with the Content-Type header
// and cache preflight response for an 3600s
res.set("Access-Control-Allow-Origin", "*");
res.set("Access-Control-Allow-Methods", "GET");
res.set("Access-Control-Allow-Headers", "Content-Type");
res.set("Access-Control-Max-Age", "3600");
// Send response to OPTIONS requests and terminate the function execution
if (req.method == 'OPTIONS')
res.status(204).send('');
// Continue with function code
...
【讨论】:
在您附加的文档中,指定使用 firebase 函数时如何处理 CORS:yourdomain.com
向 region-project.cloudfunctions.net/yourfunction
发出请求,但情况并非如此,在这种情况下您可以访问 @ 987654327@,但我必须为一个不是函数的站点创建一个POST
。顺便说一句,除非您指的是全局配置它们,否则我没有使用 Express。
有什么方法可以将这些相同的标头添加到来自sis-t.redsys.es:25443/sis/realizarPago 的响应中?如果是这样,即使它不是云功能,它也应该可以工作。
sis-t.redsys.es:25443/sis/realizarPago
只是我需要POST
的网址,在向该网址发出请求之前我不会得到回复。使用@Jason Dark 的anwser:res.set( 'Access-Control-Allow-Origin': '*' ).sendStatus(200) return res.send(200, "data": createPayment(result, key) ).end();
这会导致Can't set headers after they are sent
。
当您尝试我上面提到的内容时会发生什么? @jasonDark 的答案有一个缺陷,它一直在发送响应代码,这就是您收到错误的原因。此外,它不会发送 204 状态代码来响应预检核心选项。可能值得通过 developer.mozilla.org/en-US/docs/Web/HTTP/CORS 阅读有关 CORS 的更多信息。
我花了太多时间寻找这个!干得好以上是关于如何在 firebase 函数环境中解决 CORS?的主要内容,如果未能解决你的问题,请参考以下文章