我目前正在学习如何使用Firebase的新云函数,我遇到的问题是我无法访问我通过AJAX请求编写的函数。我得到了“No 'Access-Control-Allow-Origin'”错误。下面是我写的函数示例:

exports.test = functions.https.onRequest((request, response) => {
  response.status(500).send({test: 'Testing functions'});
})

函数位于这个url中: https://us-central1-fba-shipper-140ae.cloudfunctions.net/test

Firebase文档建议在函数中添加CORS中间件,我尝试过,但对我不起作用:https://firebase.google.com/docs/functions/http-events

我是这样做的:

var cors = require('cors');    

exports.test = functions.https.onRequest((request, response) => {
   cors(request, response, () => {
     response.status(500).send({test: 'Testing functions'});
   })
})

我做错了什么?如果你能帮我,我会很感激。

更新:

道格·史蒂文森的回答很有帮助。添加({origin: true})修复了这个问题,我还必须将response.status(500)更改为response.status(200),这是我一开始完全错过的。


当前回答

Firebase团队提供了两个示例函数来演示CORS的使用:

具有日期格式的时间服务器 要求认证的HTTPS端点

第二个示例使用与当前使用的cors不同的工作方式。

考虑像这样导入,如示例所示:

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

函数的一般形式是这样的

exports.fn = functions.https.onRequest((req, res) => {
    cors(req, res, () => {
        // your function body here - use the provided req and res from cors
    })
});

其他回答

我得到了错误,因为我调用了一个在客户端不存在的函数。例如:

firebase.functions().httpsCallable('makeSureThisStringIsCorrect');

更新答案:使用cors库与Typescript支持:

安装科尔斯

npm i -S cors
npm i --save-dev @types/cors

index.ts:

import * as cors from "cors";
const corsHandler = cors({ origin: true });

// allow cors in http function
export const myFunction = functions.https.onRequest((req, res) => {
corsHandler(req, res, async () => {

// your method body

 });
});

旧的回答: (不再工作) 找到了一种不导入任何“cors”库的方法来启用cors。它还可以使用Typescript,并在chrome版本81.0中进行了测试。

exports.createOrder = functions.https.onRequest((req, res) => {
// browsers like chrome need these headers to be present in response if the api is called from other than its base domain
  res.set("Access-Control-Allow-Origin", "*"); // you can also whitelist a specific domain like "http://127.0.0.1:4000"
  res.set("Access-Control-Allow-Headers", "Content-Type");

  // your code starts here

  //send response
  res.status(200).send();
});

一个额外的信息,只是为了那些在一段时间后谷歌这个:

如果你正在使用firebase托管,你也可以设置重写,例如一个url (firebase_hosting_host)/api/myfunction重定向到(firebase_cloudfunctions_host)/doStuff函数。这样,由于重定向是透明的并且是服务器端的,所以您不必处理cors。

你可以在firebase.json中设置一个重写部分:

"rewrites": [
        { "source": "/api/myFunction", "function": "doStuff" }
]

只有这种方式对我有效,因为我在我的请求中有授权:

exports.hello = functions.https.onRequest((request, response) => {
response.set('Access-Control-Allow-Origin', '*');
response.set('Access-Control-Allow-Credentials', 'true'); // vital
if (request.method === 'OPTIONS') {
    // Send response to OPTIONS requests
    response.set('Access-Control-Allow-Methods', 'GET');
    response.set('Access-Control-Allow-Headers', 'Content-Type');
    response.set('Access-Control-Max-Age', '3600');
    response.status(204).send('');
} else {
    const params = request.body;
    const html = 'some html';
    response.send(html)
} )};

通过这么多的搜索,我可以在相同的firebase文档中找到这个解决方案,只是在路径中实现cors:

import * as express from "express";
import * as cors from "cors";


const api = express();
api.use(cors({ origin: true }));
api.get("/url", function);

链接firebase文档:https://firebase.google.com/docs/functions/http-events