从 Netlify 服务的 Web 客户端调用时,Firebase Cloud Function 不执行

Firebase Cloud Function does not execute when called from web client served by Netlify

我一直在尝试调用 Firebase 云函数,但没有成功。

部署成功的函数为:

functions.logger.info("Hello logs!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); // this logs
exports.createAuthToken = functions.https.onRequest((request, response) => {
    functions.logger.info("Hello logs!", { structuredData: true }); // this doesn't log
    response.send("Hello from Firebase!");
});

代码的第一行显示在日志中,但从外部 Web 客户端调用时第三行没有。当我从 Google 云控制台测试 /运行 函数时,两个日志都会显示。

在 Web 客户端中,我收到错误消息:

Access to fetch at 'https://us-central1-my-project.cloudfunctions.net/create-auth-aoken?ot-auth-code=xyz' from origin 'https://my-client-url' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

所以我按照文档中的建议解决了 cors 问题:

const cors = require('cors')({
    origin: true,
});

functions.logger.info("Hello logs!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"); // this logs
exports.createAuthToken = functions.https.onRequest((request, response) => {
    cors(request, response, () => {
        functions.logger.info("Hello logs >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>!", { structuredData: true }); // this still doesn't 
        response.send("Hello from Firebase!");
    });
});

我这样调用函数: https://us-central1-my-project.cloudfunctions.net/create-auth-token?ot-auth-code=${code}&id-token=${token} 我已经尝试用我能找到的所有方法解决 cors 问题,但它不起作用。

我应该如何正确配置它才能使其正常工作?

这可以通过多种方式解决,一种是将您的请求发送到代理服务器。您的请求将如下所示:

https://cors-anywhere.herokuapp.com/https://joke-api-strict-cors.appspot.com/jokes/random

这是一个简单的解决方案,适用于开发环境,因为它是在 browser-to-server 通信上实现的。缺点是您的请求可能需要一段时间才能收到响应,因为高延迟使其看起来很慢,并且可能不适合生产环境。

另一种选择是尝试将 CORS 与 Express 结合使用。检查下面的 Node.js 代码:

const express = require('express');
const request = require('request');

const app = express();

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  next();
});

app.get('/jokes/random', (req, res) => {
  request(
    { url: 'https://joke-api-strict-cors.appspot.com/jokes/random' },
    (error, response, body) => {
      if (error || response.statusCode !== 200) {
        return res.status(500).json({ type: 'error', message: err.message });
      }

      res.json(JSON.parse(body));
    }
  )
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));

这个将作为中间件将 Access-Control-Allow-Origin: * header 应用于来自服务器的每个请求。 Same-origin 策略 即使域不同也不会介入阻止请求。

您可以查看有关如何修复 CORS 错误的完整文档:

当然可以;我将此解决方案用于 firebase,我自己滚动以简单地响应 CORS 请求:

 function MakeCORSRequest(func) {
  return functions.https.onRequest((req, res) => {
    res.set('Access-Control-Allow-Origin', '*');
    if (req.method === 'OPTIONS') {
      // Send response to OPTIONS requests
      res.set('Access-Control-Allow-Methods', 'GET, POST');
      res.set('Access-Control-Allow-Headers', 'Content-Type');
      res.set('Access-Control-Max-Age', '3600');
      res.status(204).send('');
    } else {
      return func(req, res);
    }
  });
}

它所做的只是拦截 CORS OPTIONS 请求并用 'Yes you can' 响应 - 其他请求(例如 GET/POST)它只是传递给给定的函数。它可用于包装您的端点并正确响应来自浏览器的 CORS 调用。

所以实际的终点是这样表示的:

exports.myFunction = MakeCORSRequest(async (req, response) => {
   //Do your stuff here
})

我无法解决 CORS 问题,但我确实设法通过使用 functions.https.onCall 而不是 functions.https.onRequest 使云功能最终起作用。我找到了这个答案 and followed these official docs: https://firebase.google.com/docs/functions/callable#web-version-9