我目前正在学习如何为Firebase使用新的Cloud Functions,而我遇到的问题是我无法访问通过AJAX请求编写的函数。我收到“没有'Access-Control-Allow-Origin'错误”。这是我编写的函数的示例:
exports.test = functions.https.onRequest((request, response) => {
response.status(500).send({test: 'Testing functions'});
})
该函数位于以下网址中: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)的回答很有帮助。添加({产地:真})固定的问题,我也不得不改变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
});
一条额外的信息,只是为了在一段时间后使用Google进行搜索:如果您使用的是Firebase托管,还可以设置重写,例如,像(firebase_hosting_host)/ api / myfunction这样的url重定向到( 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:
const cors = require('cors')({origin: true});
到目前为止,没有CORS解决方案对我有用。
不知道是否有人遇到过与我相同的问题,但是我以与发现的示例不同的5种方式设置了CORS,似乎没有任何效果。我与Plunker一起建立了一个最小的示例,以查看它是否确实是一个错误,但是示例运行得很漂亮。我决定检查firebase函数日志(在firebase控制台中找到),看看是否可以告诉我任何事情。我在节点服务器的代码有一对夫妇的错误,不CORS相关的,当我调试释放了我CORS错误信息。我不知道为什么与CORS无关的代码错误会返回CORS错误响应,但是它导致我在错误的兔子洞中呆了好几个小时...
tl; dr-检查您的Firebase功能日志是否没有CORS解决方案,并调试您拥有的任何错误
这可能会有所帮助。我用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);
请确保您添加了重写部分
"rewrites": [
{
"source": "/api/v1/**",
"function": "functionName"
}
]
我刚刚发表了一点关于:
https://mhaligowski.github.io/blog/2017/03/10/cors-in-cloud-functions.html
通常,您应该使用Express CORS软件包,该需要一些修改才能满足GCF / Firebase Functions中的要求。
希望有帮助!
找到了一种无需导入任何“ 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();
});
只有这种方式对我有效,因为我已获得请求的授权:
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 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
如果您不/不能使用cors插件,则setCorsHeaders()
在处理程序函数中首先调用该函数也将起作用。
回复时,也使用responseSuccess / 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));
}
值得的是,app
进入时我遇到了同样的问题onRequest
。我意识到问题是firebase函数的请求URL末尾有一个斜杠。Express在寻找,'/'
但是我没有在函数上加上斜线[project-id].cloudfunctions.net/[function-name]
。CORS错误是假阴性。当我添加结尾斜杠时,我得到了期望的响应。
如果您要在本地测试Firebase应用,则需要将功能指向localhost
而不是云。默认情况下,firebase serve
或firebase emulators:start
在Web应用程序上将功能指向服务器而不是localhost时使用。
在firebase初始化脚本之后,在html头中添加以下脚本:
<script>
firebase.functions().useFunctionsEmulator('http://localhost:5001')
</script>
将代码部署到服务器时,请确保删除此代码段。
改变对我来说true
是"*"
成功的窍门,所以它看起来像这样:
const cors = require('cors')({ origin: "*" })
我尝试了这种方法,因为通常,这是设置此响应标头的方式:
'Access-Control-Allow-Origin', '*'
请注意,这将允许任何域调用您的端点,因此并不安全。
此外,您可以在文档上阅读更多信息:https :
//github.com/expressjs/cors
如果您不使用Express或只是想使用CORS。以下代码将有助于解决
const cors = require('cors')({ origin: true, });
exports.yourfunction = functions.https.onRequest((request, response) => {
return cors(request, response, () => {
// *Your code*
});
});
使用Google Cloud Console仪表板的简单解决方案:
- 转到您的GCP控制台信息中心:
- 进入菜单
“云函数”(“计算”部分)
-
选择您的云功能,例如“ MyFunction”,右侧菜单将出现,向您显示其访问控制设置
-
单击“添加成员”,键入“ allUsers”,然后选择角色“ Cloud Function Invoker”
-
保存->现在,您应该在云功能列表中看到“允许未经身份验证”的注释
现在,通过正确配置GCP或Firebase项目,每个人都可以从Internet访问。(注意)
在我的情况下,该错误是由云函数调用程序限制访问引起的。请将allUsers添加到云函数调用程序。请点击链接。请参阅文章以获取更多信息
如果其他解决方案均无效,则可以尝试在呼叫开始时添加以下地址以启用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填写了有关此问题的错误报告
文章标签:cors , firebase , google-cloud-functions , google-cloud-platform , javascript
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!
评论已关闭!