[英]Enabling CORS in Cloud Functions for Firebase
我目前正在学习如何为 Firebase 使用新的 Cloud Functions,我遇到的问题是我无法访问我通过 AJAX 请求编写的 function。 我收到“无‘Access-Control-Allow-Origin’”错误。 这是我写的 function 的示例:
exports.test = functions.https.onRequest((request, response) => {
response.status(500).send({test: 'Testing functions'});
})
function 位于这个 url: https://us-central1-fba-shipper-140ae.cloudfunctions.net/test
Firebase 文档建议在 function 中添加 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 的使用:
第二个示例使用与您当前使用的不同的方式处理 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
})
});
您可以像这样在云功能中设置 CORS
response.set('Access-Control-Allow-Origin', '*');
无需导入cors
包
对于尝试在 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
});
还有一条信息,只是为了那些在一段时间后使用谷歌搜索的人:如果您使用的是 firebase 托管,您还可以设置重写,以便例如 (firebase_hosting_host)\/api\/myfunction 之类的 url 重定向到 ( firebase_cloudfunctions_host)\/doStuff 函数。 这样,由于重定向是透明的并且是服务器端的,因此您不必处理 cors。
您可以使用 firebase.json 中的 rewrites 部分进行设置:
"rewrites": [
{ "source": "/api/myFunction", "function": "doStuff" }
]
没有 CORS 解决方案对我有用……直到现在!<\/strong>
不知道其他人是否遇到了与我相同的问题,但我设置了 5 种与我发现的示例不同的方式来设置 CORS,但似乎没有任何效果。 我用 Plunker 建立了一个最小的例子,看看它是否真的是一个错误,但这个例子运行得很好。 我决定检查 firebase 函数日志(在 firebase 控制台中找到),看看是否能告诉我任何信息。 我的节点服务器代码中有几个错误,<\/strong>与 CORS 无关<\/strong>,当我调试时释放了我的 CORS 错误消息<\/strong>。 我不知道为什么与 CORS 无关的代码错误会返回 CORS 错误响应,但它让我在错误的兔子洞里呆了好几个小时……
tl;dr - 如果没有 CORS 解决方案有效,请检查您的 firebase 功能日志并调试您遇到的任何错误
我对@Andreys 对他自己的问题的回答有一点补充。
似乎您不必在cors(req, res, cb)
函数中调用回调,因此您只需调用函数顶部的 cors 模块,而无需将所有代码嵌入回调中。 如果您想在之后实施 cors,这要快得多。
exports.exampleFunction = functions.https.onRequest((request, response) => {
cors(request, response, () => {});
return response.send("Hello from Firebase!");
});
不要忘记在开篇文章中提到的初始化 cors:
const cors = require('cors')({origin: true});
更新:任何需要时间的响应函数都会冒这个实现出现 CORS 错误的风险,因为它没有适当的 async/await。 不要在返回静态数据的快速原型设计端点之外使用。
这可能会有所帮助。 我使用 express(自定义 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);
更新答案:<\/strong>使用带有 Typescript 支持的
cors<\/code>库:
安装
cors<\/code>
npm i -S cors
npm i --save-dev @types/cors
如果你不\/不能使用 cors 插件,首先在处理函数中调用
setCorsHeaders()<\/code>函数也可以。
回复时也使用 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));
}
使用 Google Cloud Console 仪表板的简单解决方案:
https:\/\/console.cloud.google.com\/home\/dashboard<\/a><\/blockquote>
如果有像我这样的人:如果您想从与云功能相同的项目中调用云功能,您可以初始化 firebase sdk 并使用 onCall 方法。 它将为您处理一切:
exports.newRequest = functions.https.onCall((data, context) => {
console.log(`This is the received data: ${data}.`);
return data;
})
我刚刚发表了一篇关于此的文章:
https://mhaligowski.github.io/blog/2017/03/10/cors-in-cloud-functions.html
通常,您应该使用 Express CORS 包,这需要稍微修改一下才能满足 GCF/Firebase 函数中的要求。
希望有帮助!
只有这种方式对我有用,因为我在我的请求中有授权:
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)
} )};
如果您没有在函数中捕获错误,则可能会发生 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!"
});
});
});
感谢 stackoverflow 用户: Hoang Trinh 、 Yayo Arellano和Doug Stevenson
通过"*"
更改true
对我来说是诀窍,所以它看起来像这样:
const cors = require('cors')({ origin: "*" })
我尝试了这种方法,因为通常这是设置此响应标头的方式:
'Access-Control-Allow-Origin', '*'
请注意,这将允许任何域调用您的端点,因此它不安全。
此外,您可以在文档中阅读更多信息: https ://github.com/expressjs/cors
值得我在将
app<\/code>传递到
onRequest<\/code>时遇到同样的问题。
我意识到这个问题是 firebase 函数的请求 url 上的斜杠。
Express 正在寻找
'\/'<\/code>但我在函数
[project-id].cloudfunctions.net\/[function-name]<\/code>上没有斜杠。
CORS 错误是假阴性。 当我添加斜杠时,我得到了我期望的响应。
"
如果您不使用 Express 或只是想使用 CORS。 以下代码将帮助解决
const cors = require('cors')({ origin: true, });
exports.yourfunction = functions.https.onRequest((request, response) => {
return cors(request, response, () => {
// *Your code*
});
});
如果您在本地测试 firebase 应用程序,那么您需要将函数指向
localhost<\/code>而不是云。
默认情况下,当您在 Web 应用程序上使用
firebase serve<\/code>或
firebase emulators:start<\/code>时,会将函数指向服务器而不是 localhost。
在 firebase 初始化脚本之后的 html 头中添加以下脚本:
<script>
firebase.functions().useFunctionsEmulator('http://localhost:5001')
</script>
Cloud Functions for Firebase v2现在允许您直接在 HTTP 选项中配置cors
。 它无需任何第三方 package 即可工作:
import { https } from 'firebase-functions/v2';
export myfunction = https.onRequest({ cors: true }, async (req, res) => {
// this will be invoked for any request, regardless of its origin
});
谨防:
v2
处于公开预览阶段。v1
和v2
函数。 为了提高可读性,请更新您的导入以分别访问firebase-functions/v1
或firebase-functions/v2
。补充一下我的经验。 我花了几个小时试图找出出现 CORS 错误的原因。
碰巧我重命名了我的云功能(在大升级后我第一次尝试)。
因此,当我的 firebase 应用程序使用不正确的名称调用云函数时,它应该抛出 404 错误,而不是 CORS 错误。
修复我的 firebase 应用程序中的云函数名称解决了这个问题。
我在这里填写了关于此问题的错误报告https://firebase.google.com/support/troubleshooter/report/bugs
从这么多搜索中,我可以在同一个 firebase 文档中找到这个解决方案,只需在路径中实现 cors:
import * as express from "express";
import * as cors from "cors";
const api = express();
api.use(cors({ origin: true }));
api.get("/url", function);
如果您更喜欢制作单个处理函数<\/strong>( 参考答案<\/a>)
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
我收到错误是因为我正在调用客户端不存在的函数。 例如:
firebase.functions().httpsCallable('makeSureThisStringIsCorrect');
在 devtool 控制台中使用相同的访问允许控制源错误,我发现了其他具有更现代语法的解决方案:
我的 CORS 问题出在存储(而不是 RTDB 和浏览器......),然后我没有信用卡(按照上述解决方案的要求),我的无信用卡解决方案是:
安装 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
在我的情况下,错误是由云函数调用程序限制访问引起的。 请将 allUsers 添加到云函数调用程序。 请抓住链接<\/a>。 请参阅文章<\/a>了解更多信息
"如果其他解决方案都不起作用,您可以尝试在调用开始时添加以下地址以启用 CORS - 重定向:
https:\/\/cors-anywhere.herokuapp.com\/<\/a>
带有 JQuery AJAX 请求的示例代码:
请参阅下文,了解我如何使用 CORS 设置我的 Express。
“https:\/\/pericope.app”是我的 Firebase 项目的自定义域。
看起来所有其他答案都推荐
origin:true<\/code>或
*<\/code> 。
我很犹豫是否允许所有来源,因为它会允许其他任何人访问 api。 如果您正在创建公共服务,那很好,但如果您对数据做任何事情,那是有风险的,因为它是一个特权环境。 例如,此管理 SDK 会绕过您为 Firestore 或 Storage 设置的任何安全规则。
//Express
const express = require('express');
const app = express();
const cors = require('cors');
app.use(cors({
origin: 'https://pericope.app'
}));
我已经尝试了很长时间。
当我进行此更改时,它终于奏效了。
app.get('/create-customer', (req, res) => {
return cors()(req, res, () => {
... your code ...
最大的不同是我使用cors()(req, res...
而不是直接cors(req, res...
它现在完美运行。
在您的 https.onRequest 上使用 cors 和Typescript<\/strong> ,如下所示:
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()}`);
});
});
云功能日志记录会有所帮助,请检查您是否卡住了。
我的问题原来是我的云函数上的类型错误,其中我有一个预期字符串的数字:
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 解决方案添加到您的函数代码中,例如:
exports.sendMail = functions.https.onRequest((request, response) => {
response.set("Access-Control-Allow-Origin", "*");
response.send("Hello from Firebase!");
});
这个老问题,但是谢谢格莱布·多尔齐科夫
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.