我目前正在学习如何使用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),这是我一开始完全错过的。
通过“*”改变true对我来说很有用,所以它看起来是这样的:
const cors = require('cors')({ origin: "*" })
我尝试了这种方法,因为在一般情况下,这是响应头的设置方式:
'Access-Control-Allow-Origin', '*'
请注意,这将允许任何域调用您的端点,因此它是不安全的。
此外,你可以阅读更多关于文档的内容:
https://github.com/expressjs/cors
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
})
});
如果你不/不能使用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));
}
在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
更新答案:使用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();
});
如果有像我这样的人:如果你想在同一个项目中调用云函数,你可以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