在 Cloud Functions for Firebase 中启用 CORS
Enabling CORS in Cloud Functions for Firebase
我目前正在学习如何使用新的 Cloud Functions for 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'});
})
})
我做错了什么?如果对此有任何帮助,我将不胜感激。
更新:
Doug Stevenson 的回答很有帮助。添加 ({origin: true}) 解决了这个问题,我还不得不将 response.status(500)
更改为 response.status(200)
,我一开始完全错过了。
Firebase 团队提供了两个 sample functions 来演示 CORS 的使用:
第二个示例使用与您当前使用的不同的方式处理 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
})
});
我刚刚就此发表了一篇小文章:
https://mhaligowski.github.io/blog/2017/03/10/cors-in-cloud-functions.html
一般来说,您应该使用 Express CORS package,这需要一些技巧才能满足 GCF/Firebase 函数中的要求。
希望对您有所帮助!
一条额外的信息,只是为了那些在一段时间后谷歌搜索的人:
如果您使用的是 firebase 托管,您还可以设置重写,例如 url like (firebase_hosting_host)/api/myfunction 重定向到 (firebase_cloudfunctions_host)/doStuff 函数.这样,由于重定向是透明的并且在服务器端进行,因此您不必处理 cors。
您可以在 firebase.json 中使用重写部分进行设置:
"rewrites": [
{ "source": "/api/myFunction", "function": "doStuff" }
]
我对@Andreys 对他自己的问题的回答有一点补充。
看来您不必在 cors(req, res, cb)
函数中调用回调,因此您只需在函数顶部调用 cors 模块即可,而无需将所有代码嵌入回调中。如果你想在之后实施 cors,这会快得多。
exports.exampleFunction = functions.https.onRequest((request, response) => {
cors(request, response, () => {});
return response.send("Hello from Firebase!");
});
不要忘记初始化cors,如开头所述post:
const cors = require('cors')({origin: true});
更新: 任何需要时间的响应函数在这个实现中都有 CORS 错误的风险,因为它没有合适的 async/await。不要在 return 静态数据的快速原型端点之外使用。
对于任何试图在 Typescript 中执行此操作的人来说,这是代码:
import * as cors from 'cors';
const corsHandler = cors({origin: true});
export const exampleFunction= functions.https.onRequest(async (request, response) => {
corsHandler(request, response, () => {});
//Your code here
});
没有适合我的 CORS 解决方案...直到现在!
不确定是否有其他人 运行 遇到了与我相同的问题,但我从我发现的示例中以 5 种不同的方式设置了 CORS,但似乎没有任何效果。我用 Plunker 建立了一个最小的例子,看看它是否真的是一个错误,但是这个例子 运行 很漂亮。我决定检查 firebase 函数日志(在 firebase 控制台中找到),看看是否可以告诉我任何信息。 我的节点服务器代码中有几个错误,与 CORS 无关,当我调试时 释放了我的 CORS 错误消息。我不知道为什么与 CORS 无关的代码错误 returns CORS 错误响应,但它让我误入了错误的兔子洞好几个小时...
tl;dr - 如果 CORS 解决方案不起作用,请检查你的 firebase 函数日志,并调试你遇到的任何错误
您可以像这样在云函数中设置 CORS
response.set('Access-Control-Allow-Origin', '*');
无需导入 cors
包
值得一提的是,我在将 app
传递给 onRequest
时遇到了同样的问题。我意识到问题是 firebase 函数请求 url 的尾部斜杠。 Express 正在寻找 '/'
,但我没有函数 [project-id].cloudfunctions.net/[function-name]
的尾部斜线。 CORS 错误是假阴性。当我添加尾部斜杠时,我得到了预期的响应。
如果您不使用 Express 或只是想使用 CORS。下面的代码将有助于解决
const cors = require('cors')({ origin: true, });
exports.yourfunction = functions.https.onRequest((request, response) => {
return cors(request, response, () => {
// *Your code*
});
});
只有这种方式对我有用,因为我在我的请求中获得了授权:
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)
} )};
这可能会有帮助。
我用 express(custom URL)
创建了 firebase HTTP 云函数
const express = require('express');
const bodyParser = require('body-parser');
const cors = require("cors");
const app = express();
const main = express();
app.post('/endpoint', (req, res) => {
// code here
})
app.use(cors({ origin: true }));
main.use(cors({ origin: true }));
main.use('/api/v1', app);
main.use(bodyParser.json());
main.use(bodyParser.urlencoded({ extended: false }));
module.exports.functionName = functions.https.onRequest(main);
请确保您添加了重写部分
"rewrites": [
{
"source": "/api/v1/**",
"function": "functionName"
}
]
如果有像我这样的人:如果你想从与云函数本身相同的项目中调用云函数,你可以初始化 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:
如果您在本地测试 firebase 应用程序,则需要将函数指向 localhost
而不是云。默认情况下,firebase serve
或 firebase emulators:start
将函数指向服务器而不是本地主机,当您在 Web 应用程序上使用它时。
在 firebase 初始化脚本之后的 html 头部添加以下脚本:
<script>
firebase.functions().useFunctionsEmulator('http://localhost:5001')
</script>
Make sure to remove this snippet when deploying code to server.
如果您不t/can不使用 cors 插件,则在处理程序函数中首先调用 setCorsHeaders()
函数也可以。
回复时也使用 respondSuccess/Error 功能。
const ALLOWED_ORIGINS = ["http://localhost:9090", "https://sub.example.com", "https://example.com"]
// Set CORS headers for preflight requests
function setCorsHeaders (req, res) {
var originUrl = "http://localhost:9090"
if(ALLOWED_ORIGINS.includes(req.headers.origin)){
originUrl = req.headers.origin
}
res.set('Access-Control-Allow-Origin', originUrl);
res.set('Access-Control-Allow-Credentials', 'true');
if (req.method === 'OPTIONS') {
// Send response to OPTIONS requests
res.set('Access-Control-Allow-Methods', 'GET,POST','PUT','DELETE');
res.set('Access-Control-Allow-Headers', 'Bearer, Content-Type');
res.set('Access-Control-Max-Age', '3600');
res.status(204).send('');
}
}
function respondError (message, error, code, res) {
var response = {
message: message,
error: error
}
res.status(code).end(JSON.stringify(response));
}
function respondSuccess (result, res) {
var response = {
message: "OK",
result: result
}
res.status(200).end(JSON.stringify(response));
}
在我的案例中,错误是由云函数调用程序限制访问引起的。请将 allUsers 添加到云函数调用程序。请抓住 link. Please refer to article 了解更多信息
将 true
更改为 "*"
对我有用,所以它看起来像这样:
const cors = require('cors')({ origin: "*" })
我尝试了这种方法,因为通常情况下,响应 header 是这样设置的:
'Access-Control-Allow-Origin', '*'
请注意,这将允许任何域调用您的端点,因此不安全。
此外,您还可以阅读更多文档:
https://github.com/expressjs/cors
更新的答案: 使用支持 Typescript 的 cors
库:
安装cors
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();
});
如果其他解决方案中的 none 有效,您可以尝试在调用开头添加以下地址以启用 CORS - 重定向:
带有 JQuery AJAX 请求的示例代码:
$.ajax({
url: 'https://cors-anywhere.herokuapp.com/https://fir-agilan.web.app/gmail?mail=asd@gmail.com,
type: 'GET'
});
补充一下我的经验。
我花了几个小时试图找出我出现 CORS 错误的原因。
碰巧我重命名了我的云函数(我在大升级后第一次尝试)。
因此,当我的 firebase 应用程序使用不正确的名称调用云函数时,它应该抛出 404 错误,而不是 CORS 错误。
修复我的 firebase 应用中的云函数名称解决了这个问题。
我已经在此处填写了有关此问题的错误报告
https://firebase.google.com/support/troubleshooter/report/bugs
使用 Google 云控制台仪表板的简单解决方案:
- 转到您的 GCP 控制台仪表板:
- 转到菜单
"Cloud Functions" ("Compute" section)
Select 您的云功能,例如“MyFunction”,右侧应该会出现一个侧边菜单,向您显示它的访问控制设置
点击“添加成员”,输入“allUsers”和select角色“Cloud Function Invoker”
保存 -> 现在,您应该会在云函数列表中看到“允许未经身份验证”的备注
现在每个人都可以通过正确配置访问您的 GCP 或 Firebase 项目。 (小心)
如果您没有捕获函数中的错误,可能会发生 cors 错误。我的建议是在你的 corsHandler
中实现一个 try catch
const corsHandler = (request, response, handler) => {
cors({ origin: true })(request, response, async () => {
try {
await handler();
}
catch (e) {
functions.logger.error('Error: ' + e);
response.statusCode = 500;
response.send({
'status': 'ERROR' //Optional: customize your error message here
});
}
});
};
用法:
exports.helloWorld = functions.https.onRequest((request, response) => {
corsHandler(request, response, () => {
functions.logger.info("Hello logs!");
response.send({
"data": "Hello from Firebase!"
});
});
});
感谢 Whosebug 用户:Hoang Trinh, and
通过大量搜索,我可以在同一个 firebase 文档中找到这个解决方案,只需在路径中实现 cors:
import * as express from "express";
import * as cors from "cors";
const api = express();
api.use(cors({ origin: true }));
api.get("/url", function);
Link firebase 文档:https://firebase.google.com/docs/functions/http-events
请参阅下文了解我如何使用 CORS 设置我的 Express。
'https://pericope.app' 是我的 Firebase 项目的自定义域。
看起来所有其他答案都推荐 origin:true
或 *
。
我犹豫是否允许所有来源,因为它会允许其他任何人访问 api。如果您正在创建一个 public 服务,那很好,但是如果您对您的数据做任何事情,那将是有风险的,因为它是一个特权环境。例如,此管理 SDK 会绕过您为 Firestore 或存储设置的任何安全规则。
//Express
const express = require('express');
const app = express();
const cors = require('cors');
app.use(cors({
origin: 'https://pericope.app'
}));
如果您更喜欢单一处理函数 ()
const applyMiddleware = handler => (req, res) => {
return cors(req, res, () => {
return handler(req, res)
})
}
exports.handler = functions.https.onRequest(applyMiddleware(handler))
我是 Firebase 的初学者(30 分钟前注册)。我的问题是我调用了我的端点
https://xxxx-default-rtdb.firebaseio.com/myendpoint
而不是
https://xxxx-default-rtdb.firebaseio.com/myendpoint.json
如果您刚开始使用 Firebase,请确保不要忘记 .json
扩展。
我已经尝试了很长时间了。
当我进行此更改时,它终于起作用了。
app.get('/create-customer', (req, res) => {
return cors()(req, res, () => {
... your code ...
最大的不同是我用了cors()(req, res...
而不是直接cors(req, res...
现在完美运行。
我收到错误是因为我正在调用客户端不存在的函数。例如:
firebase.functions().httpsCallable('makeSureThisStringIsCorrect');
使用 Typescript 在 https.onRequest 上使用 cors,如下所示:
import * as cors from 'cors';
const corsHandler = cors({origin: true});
export const pingFunctionWithCorsAllowed = functions.https.onRequest((request, response) => {
corsHandler(request, response, () => {
response.send(`Ping from Firebase (with CORS handling)! ${new Date().toISOString()}`);
});
});
来自Source
云功能日志记录有帮助,请检查您是否卡住了。
我的问题原来是我的云函数的类型错误,其中我有一个需要字符串的数字:
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received type number (1)
出于某种原因,这让我在前端出现了 cors 错误,并且浪费了几个小时。
- 进入你的Google Cloud Functions。您以前可能没有见过这个平台,但这就是您解决这个 Firebase 问题的方法。
- 找到您要搜索的 Firebase 函数并点击名称。如果此页面为空白,您可能需要搜索 Cloud Functions 并从结果中 select 页面。
- 找到您的函数,单击名称。
- 转到权限选项卡。单击添加(添加用户)。
- 根据新原则,键入 'allUsers' -- 它应该在您完成键入之前自动完成。
- 在 select 角色下,搜索 Cloud Functions,然后选择 Invoker。
- 保存。
- 等几分钟。
这应该可以解决问题。如果没有,请执行此操作并向您的函数代码添加一个 CORS 解决方案,例如:
exports.sendMail = functions.https.onRequest((request, response) => {
response.set("Access-Control-Allow-Origin", "*");
response.send("Hello from Firebase!");
});
在 devtool 控制台中出现相同的 access allow control origin 错误,我发现了其他具有更现代语法的解决方案:
我的 CORS 问题是存储(而不是 RTDB 和浏览器......),然后我没有信用卡(如上述解决方案所要求的),我的 no-credit卡片解决方案是:
安装 gsutil:
https://cloud.google.com/storage/docs/gsutil_install#linux-and-macos
创建一个 cors.json 文件以使用 gsutil
通过终端加载
gsutil cors set cors.json gs://[ your-bucket ]/-1.appspot.com
https://firebase.google.com/docs/storage/web/download-files#cors_configuration
我目前正在学习如何使用新的 Cloud Functions for 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'});
})
})
我做错了什么?如果对此有任何帮助,我将不胜感激。
更新:
Doug Stevenson 的回答很有帮助。添加 ({origin: true}) 解决了这个问题,我还不得不将 response.status(500)
更改为 response.status(200)
,我一开始完全错过了。
Firebase 团队提供了两个 sample functions 来演示 CORS 的使用:
第二个示例使用与您当前使用的不同的方式处理 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
})
});
我刚刚就此发表了一篇小文章:
https://mhaligowski.github.io/blog/2017/03/10/cors-in-cloud-functions.html
一般来说,您应该使用 Express CORS package,这需要一些技巧才能满足 GCF/Firebase 函数中的要求。
希望对您有所帮助!
一条额外的信息,只是为了那些在一段时间后谷歌搜索的人: 如果您使用的是 firebase 托管,您还可以设置重写,例如 url like (firebase_hosting_host)/api/myfunction 重定向到 (firebase_cloudfunctions_host)/doStuff 函数.这样,由于重定向是透明的并且在服务器端进行,因此您不必处理 cors。
您可以在 firebase.json 中使用重写部分进行设置:
"rewrites": [
{ "source": "/api/myFunction", "function": "doStuff" }
]
我对@Andreys 对他自己的问题的回答有一点补充。
看来您不必在 cors(req, res, cb)
函数中调用回调,因此您只需在函数顶部调用 cors 模块即可,而无需将所有代码嵌入回调中。如果你想在之后实施 cors,这会快得多。
exports.exampleFunction = functions.https.onRequest((request, response) => {
cors(request, response, () => {});
return response.send("Hello from Firebase!");
});
不要忘记初始化cors,如开头所述post:
const cors = require('cors')({origin: true});
更新: 任何需要时间的响应函数在这个实现中都有 CORS 错误的风险,因为它没有合适的 async/await。不要在 return 静态数据的快速原型端点之外使用。
对于任何试图在 Typescript 中执行此操作的人来说,这是代码:
import * as cors from 'cors';
const corsHandler = cors({origin: true});
export const exampleFunction= functions.https.onRequest(async (request, response) => {
corsHandler(request, response, () => {});
//Your code here
});
没有适合我的 CORS 解决方案...直到现在!
不确定是否有其他人 运行 遇到了与我相同的问题,但我从我发现的示例中以 5 种不同的方式设置了 CORS,但似乎没有任何效果。我用 Plunker 建立了一个最小的例子,看看它是否真的是一个错误,但是这个例子 运行 很漂亮。我决定检查 firebase 函数日志(在 firebase 控制台中找到),看看是否可以告诉我任何信息。 我的节点服务器代码中有几个错误,与 CORS 无关,当我调试时 释放了我的 CORS 错误消息。我不知道为什么与 CORS 无关的代码错误 returns CORS 错误响应,但它让我误入了错误的兔子洞好几个小时...
tl;dr - 如果 CORS 解决方案不起作用,请检查你的 firebase 函数日志,并调试你遇到的任何错误
您可以像这样在云函数中设置 CORS
response.set('Access-Control-Allow-Origin', '*');
无需导入 cors
包
值得一提的是,我在将 app
传递给 onRequest
时遇到了同样的问题。我意识到问题是 firebase 函数请求 url 的尾部斜杠。 Express 正在寻找 '/'
,但我没有函数 [project-id].cloudfunctions.net/[function-name]
的尾部斜线。 CORS 错误是假阴性。当我添加尾部斜杠时,我得到了预期的响应。
如果您不使用 Express 或只是想使用 CORS。下面的代码将有助于解决
const cors = require('cors')({ origin: true, });
exports.yourfunction = functions.https.onRequest((request, response) => {
return cors(request, response, () => {
// *Your code*
});
});
只有这种方式对我有用,因为我在我的请求中获得了授权:
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)
} )};
这可能会有帮助。 我用 express(custom URL)
创建了 firebase HTTP 云函数const express = require('express');
const bodyParser = require('body-parser');
const cors = require("cors");
const app = express();
const main = express();
app.post('/endpoint', (req, res) => {
// code here
})
app.use(cors({ origin: true }));
main.use(cors({ origin: true }));
main.use('/api/v1', app);
main.use(bodyParser.json());
main.use(bodyParser.urlencoded({ extended: false }));
module.exports.functionName = functions.https.onRequest(main);
请确保您添加了重写部分
"rewrites": [
{
"source": "/api/v1/**",
"function": "functionName"
}
]
如果有像我这样的人:如果你想从与云函数本身相同的项目中调用云函数,你可以初始化 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:
如果您在本地测试 firebase 应用程序,则需要将函数指向 localhost
而不是云。默认情况下,firebase serve
或 firebase emulators:start
将函数指向服务器而不是本地主机,当您在 Web 应用程序上使用它时。
在 firebase 初始化脚本之后的 html 头部添加以下脚本:
<script>
firebase.functions().useFunctionsEmulator('http://localhost:5001')
</script>
Make sure to remove this snippet when deploying code to server.
如果您不t/can不使用 cors 插件,则在处理程序函数中首先调用 setCorsHeaders()
函数也可以。
回复时也使用 respondSuccess/Error 功能。
const ALLOWED_ORIGINS = ["http://localhost:9090", "https://sub.example.com", "https://example.com"]
// Set CORS headers for preflight requests
function setCorsHeaders (req, res) {
var originUrl = "http://localhost:9090"
if(ALLOWED_ORIGINS.includes(req.headers.origin)){
originUrl = req.headers.origin
}
res.set('Access-Control-Allow-Origin', originUrl);
res.set('Access-Control-Allow-Credentials', 'true');
if (req.method === 'OPTIONS') {
// Send response to OPTIONS requests
res.set('Access-Control-Allow-Methods', 'GET,POST','PUT','DELETE');
res.set('Access-Control-Allow-Headers', 'Bearer, Content-Type');
res.set('Access-Control-Max-Age', '3600');
res.status(204).send('');
}
}
function respondError (message, error, code, res) {
var response = {
message: message,
error: error
}
res.status(code).end(JSON.stringify(response));
}
function respondSuccess (result, res) {
var response = {
message: "OK",
result: result
}
res.status(200).end(JSON.stringify(response));
}
在我的案例中,错误是由云函数调用程序限制访问引起的。请将 allUsers 添加到云函数调用程序。请抓住 link. Please refer to article 了解更多信息
将 true
更改为 "*"
对我有用,所以它看起来像这样:
const cors = require('cors')({ origin: "*" })
我尝试了这种方法,因为通常情况下,响应 header 是这样设置的:
'Access-Control-Allow-Origin', '*'
请注意,这将允许任何域调用您的端点,因此不安全。
此外,您还可以阅读更多文档: https://github.com/expressjs/cors
更新的答案: 使用支持 Typescript 的 cors
库:
安装cors
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();
});
如果其他解决方案中的 none 有效,您可以尝试在调用开头添加以下地址以启用 CORS - 重定向:
带有 JQuery AJAX 请求的示例代码:
$.ajax({
url: 'https://cors-anywhere.herokuapp.com/https://fir-agilan.web.app/gmail?mail=asd@gmail.com,
type: 'GET'
});
补充一下我的经验。 我花了几个小时试图找出我出现 CORS 错误的原因。
碰巧我重命名了我的云函数(我在大升级后第一次尝试)。
因此,当我的 firebase 应用程序使用不正确的名称调用云函数时,它应该抛出 404 错误,而不是 CORS 错误。
修复我的 firebase 应用中的云函数名称解决了这个问题。
我已经在此处填写了有关此问题的错误报告 https://firebase.google.com/support/troubleshooter/report/bugs
使用 Google 云控制台仪表板的简单解决方案:
- 转到您的 GCP 控制台仪表板:
- 转到菜单
"Cloud Functions" ("Compute" section)
Select 您的云功能,例如“MyFunction”,右侧应该会出现一个侧边菜单,向您显示它的访问控制设置
点击“添加成员”,输入“allUsers”和select角色“Cloud Function Invoker”
保存 -> 现在,您应该会在云函数列表中看到“允许未经身份验证”的备注
现在每个人都可以通过正确配置访问您的 GCP 或 Firebase 项目。 (小心)
如果您没有捕获函数中的错误,可能会发生 cors 错误。我的建议是在你的 corsHandler
中实现一个try catch
const corsHandler = (request, response, handler) => {
cors({ origin: true })(request, response, async () => {
try {
await handler();
}
catch (e) {
functions.logger.error('Error: ' + e);
response.statusCode = 500;
response.send({
'status': 'ERROR' //Optional: customize your error message here
});
}
});
};
用法:
exports.helloWorld = functions.https.onRequest((request, response) => {
corsHandler(request, response, () => {
functions.logger.info("Hello logs!");
response.send({
"data": "Hello from Firebase!"
});
});
});
感谢 Whosebug 用户:Hoang Trinh,
通过大量搜索,我可以在同一个 firebase 文档中找到这个解决方案,只需在路径中实现 cors:
import * as express from "express";
import * as cors from "cors";
const api = express();
api.use(cors({ origin: true }));
api.get("/url", function);
Link firebase 文档:https://firebase.google.com/docs/functions/http-events
请参阅下文了解我如何使用 CORS 设置我的 Express。
'https://pericope.app' 是我的 Firebase 项目的自定义域。
看起来所有其他答案都推荐 origin:true
或 *
。
我犹豫是否允许所有来源,因为它会允许其他任何人访问 api。如果您正在创建一个 public 服务,那很好,但是如果您对您的数据做任何事情,那将是有风险的,因为它是一个特权环境。例如,此管理 SDK 会绕过您为 Firestore 或存储设置的任何安全规则。
//Express
const express = require('express');
const app = express();
const cors = require('cors');
app.use(cors({
origin: 'https://pericope.app'
}));
如果您更喜欢单一处理函数 (
const applyMiddleware = handler => (req, res) => {
return cors(req, res, () => {
return handler(req, res)
})
}
exports.handler = functions.https.onRequest(applyMiddleware(handler))
我是 Firebase 的初学者(30 分钟前注册)。我的问题是我调用了我的端点
https://xxxx-default-rtdb.firebaseio.com/myendpoint
而不是
https://xxxx-default-rtdb.firebaseio.com/myendpoint.json
如果您刚开始使用 Firebase,请确保不要忘记 .json
扩展。
我已经尝试了很长时间了。
当我进行此更改时,它终于起作用了。
app.get('/create-customer', (req, res) => {
return cors()(req, res, () => {
... your code ...
最大的不同是我用了cors()(req, res...
而不是直接cors(req, res...
现在完美运行。
我收到错误是因为我正在调用客户端不存在的函数。例如:
firebase.functions().httpsCallable('makeSureThisStringIsCorrect');
使用 Typescript 在 https.onRequest 上使用 cors,如下所示:
import * as cors from 'cors';
const corsHandler = cors({origin: true});
export const pingFunctionWithCorsAllowed = functions.https.onRequest((request, response) => {
corsHandler(request, response, () => {
response.send(`Ping from Firebase (with CORS handling)! ${new Date().toISOString()}`);
});
});
来自Source
云功能日志记录有帮助,请检查您是否卡住了。
我的问题原来是我的云函数的类型错误,其中我有一个需要字符串的数字:
TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received type number (1)
出于某种原因,这让我在前端出现了 cors 错误,并且浪费了几个小时。
- 进入你的Google Cloud Functions。您以前可能没有见过这个平台,但这就是您解决这个 Firebase 问题的方法。
- 找到您要搜索的 Firebase 函数并点击名称。如果此页面为空白,您可能需要搜索 Cloud Functions 并从结果中 select 页面。
- 找到您的函数,单击名称。
- 转到权限选项卡。单击添加(添加用户)。
- 根据新原则,键入 'allUsers' -- 它应该在您完成键入之前自动完成。
- 在 select 角色下,搜索 Cloud Functions,然后选择 Invoker。
- 保存。
- 等几分钟。
这应该可以解决问题。如果没有,请执行此操作并向您的函数代码添加一个 CORS 解决方案,例如:
exports.sendMail = functions.https.onRequest((request, response) => {
response.set("Access-Control-Allow-Origin", "*");
response.send("Hello from Firebase!");
});
在 devtool 控制台中出现相同的 access allow control origin 错误,我发现了其他具有更现代语法的解决方案:
我的 CORS 问题是存储(而不是 RTDB 和浏览器......),然后我没有信用卡(如上述解决方案所要求的),我的 no-credit卡片解决方案是:
安装 gsutil: https://cloud.google.com/storage/docs/gsutil_install#linux-and-macos
创建一个 cors.json 文件以使用 gsutil
通过终端加载
gsutil cors set cors.json gs://[ your-bucket ]/-1.appspot.com
https://firebase.google.com/docs/storage/web/download-files#cors_configuration