我已经查看了Firebase关于CORS问题的几乎每一个StackOverflow问题,但它们似乎都不起作用。
我在Firebase函数上有一些云函数,如果用户经过身份验证,它们会上传图像。我有两个文件:index.js
和user.js
。
index.js
:中的代码段
const functions = require("firebase-functions");
const FBAuth = require("./util/fbAuth");
const app = require("express")();
const cors = require("cors")({origin: true});
app.use(cors);
// FBAuth gets a bearer token from firebase and authenticates
app.post("/user/image", FBAuth, uploadImage);
exports.api = functions.https.onRequest(app);
来自user.js
的代码段
exports.uploadImage = (req, res) => {
const BusBoy = require('busboy');
const path = require('path');
const os = require('os');
const fs = require('fs');
const busboy = new BusBoy({ headers: req.headers });
let imageToBeUploaded = {};
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
if (mimetype !== 'image/jpeg' && mimetype !== 'image/png') {
return res.status(400).json({ error: 'Wrong file type submitted' });
}
const filepath = path.join(os.tmpdir(), filename);
imageToBeUploaded = { filepath, mimetype };
file.pipe(fs.createWriteStream(filepath));
});
busboy.on('finish', () => {
admin
.storage()
.bucket()
.upload(imageToBeUploaded.filepath, {
resumable: false,
metadata: {
metadata: {
contentType: imageToBeUploaded.mimetype
}
}
})
.then(() => {
const imageUrl = `https://firebasestorage.googleapis.com/v0/b/${
config.storageBucket
}/o/${imageFileName}?alt=media`;
return db.doc(`/users/${req.user.handle}`).update({ imageUrl });
})
.then(() => {
return res.json({ message: 'image uploaded successfully' });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: 'something went wrong' });
});
});
busboy.end(req.rawBody);
};
前端在redux/React中,由Firebase web应用程序托管:
export const uploadImage = (formData) => (dispatch) => {
dispatch({ type: LOADING_USER });
axios
.post("/user/image", formData)
.then(() => {
dispatch(getUserData());
})
.catch((err) => console.log(err));
};
我尝试过的:
我试过使用gsutil cors set cors.json
。问题是我所有的其他功能都能正常工作,只有当我将图像上传到谷歌存储时才会失败。
错误:
CORS策略阻止了从"link.firebaseapp.com"访问"cloudfunction/user/image"上的XMLHttpRequest:请求的资源上不存在"Access Control Allow origin"标头。
我做错了什么?
根据文档,origin: true
表示原点必须与Origin
标头匹配。相反,您可以允许任何带有origin: "*"
的原点,或者只保留为空,因为这是默认选项:
const cors = require("cors");
app.use(cors());
您可以尝试这个(没有cors(
var allowCrossDomain = function (req, res, next) {
var allowedOrigins = [
'http://link.firebaseapp.com',
];
var origin = req.headers.origin;
if (allowedOrigins.indexOf(origin) > -1) {
res.setHeader('Access-Control-Allow-Origin', origin);
}
res.header('Access-Control-Allow-Origin', '*');
/* if any specific then : */
// res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
// res.header('Access-Control-Allow-Credentials', 'true');
// res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, accesstoken, latitude, longitude, source');
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.send(200);
} else {
next();
}
};
app.use(allowCrossDomain);
因此,经过多次调试并恢复到没有CORS问题的git提交后,我想我会再次向任何有此问题的人提及它。
我按照@ariel说的步骤做了,但没有成功。事实证明,当我在functions
中初始化firebase应用程序时,我出现了一个错误,我评论道:
const admin = require("firebase-admin");
admin.initializeApp();
// const serviceAccount = require("../db.json");
// admin.initializeApp({
// credential: admin.credential.cert(serviceAccount),
// databaseURL: "https://myurl.firebaseio.com",
// });
const db = admin.firestore();
module.exports = { admin, db };
老实说,我不确定为什么它以前不起作用,我也不确定这是否是解决方案,但我不再遇到CORS问题,所以对于其他遇到这个问题的人来说,在它起作用时恢复到提交并从那里开始是一个很好的开始。