我目前正在学习如何使用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托管,你也可以设置重写,例如一个url (firebase_hosting_host)/api/myfunction重定向到(firebase_cloudfunctions_host)/doStuff函数。这样,由于重定向是透明的并且是服务器端的,所以您不必处理cors。

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

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

其他回答

如果有像我这样的人:如果你想在同一个项目中调用云函数,你可以init firebase sdk并使用onCall方法。它会为你处理一切:

exports.newRequest = functions.https.onCall((data, context) => {
    console.log(`This is the received data: ${data}.`);
    return data;
})

像这样调用这个函数:

// Init the firebase SDK first    
const functions = firebase.functions();
const addMessage = functions.httpsCallable(`newRequest`);

Firebase文档:https://firebase.google.com/docs/functions/callable

如果你不能初始化SDK,以下是其他建议的精髓:

如果在默认位置使用firebase托管和主机,请选择“重写:https://firebase.google.com/docs/hosting/full-config#rewrites” 或者像krishnazden建议的那样使用CORS: https://stackoverflow.com/a/53845986/1293220

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

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的初学者(30分钟前注册的)。我的问题是我调用了端点

https://xxxx-default-rtdb.firebaseio.com/myendpoint

而不是

https://xxxx-default-rtdb.firebaseio.com/myendpoint.json

如果您刚开始使用Firebase,请确保不要忘记.json扩展名。

更新答案:使用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();
});

Go into your Google Cloud Functions. You may have not seen this platform before, but it's how you'll fix this Firebase problem. Find the Firebase function you're searching for and click on the name. If this page is blank, you may need to search for Cloud Functions and select the page from the results. Find your function, click on the name. Go to the permissions tab. Click Add (to add user). Under new principles, type 'allUsers' -- it should autocomplete before you finish typing. Under select a role, search for Cloud Functions, then choose Invoker. Save. Wait a couple minutes.

这应该能解决问题。如果没有,就这样做,并在你的函数代码中添加一个CORS解决方案,比如:

  exports.sendMail = functions.https.onRequest((request, response) => {
  response.set("Access-Control-Allow-Origin", "*");
  response.send("Hello from Firebase!");
});