如何解决Express JS部署后的CORS跨域问题?
部署网站后遭遇CORS错误,求解决方法
报错信息
Access to XMLHttpRequest at 'https://backend-heroku.herokuapp.com/posts' from origin 'https://website1231.web.app' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
已尝试的所有方法(均无效)
- 给所有请求单独设置响应头:
res.set("Access-Control-Allow-Origin", "*")
- 直接使用CORS中间件:
const express = require('express') const app = express () const cors = require('cors') app.use(cors())
- 配置CORS选项后启用中间件:
let corsOptions = { origin: true, methods: "GET,HEAD,PUT,PATCH,POST,DELETE", credentials: true }; app.use(cors(corsOptions));
- 在具体路由中单独启用CORS并设置响应头:
app.get("/posts", cors(), (request, response) => { response.set("Access-Control-Allow-Origin", "*"); let posts = []; db.collection("posts") .orderBy("date", "desc") .get() .then((snapshot) => { snapshot.forEach((doc) => { posts.push(doc.data()); }); response.send(posts); }); console.log("posts=", posts); });
- 自定义中间件设置CORS头:
app.use((req, res, next) => { res.append("Access-Control-Allow-Origin", ["*"]); res.append("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE"); res.append("Access-Control-Allow-Headers", "Content-Type"); next(); });
- 处理OPTIONS请求的自定义中间件:
app.use((req, res, next) => { res.header("Access-Control-Allow-Origin", "*") res.header( "Access-Control-Allow-Headers", "Origin, X-Requested, Content-Type, Accept Authorization" ) if (req.method === "OPTIONS") { res.header( "Access-Control-Allow-Methods", "POST, PUT, PATCH, GET, DELETE" ) return res.status(200).json({}) } next() })
疑问
以上方法全试过都没用,到底该怎么解决?是Heroku或Firebase的安全设置里有需要调整的选项,还是我的代码本身存在错误?
之前本地环境下(前端Firebase+后端localhost)能正常处理CORS,本来以为部署到Heroku后也能正常工作,结果出了问题。
完整后端代码(index.js)
//========DEPENDENCIES========== const express = require("express"); const { initializeApp, cert } = require("firebase-admin/app"); const { getFirestore } = require("firebase-admin/firestore"); const { getStorage } = require("firebase-admin/storage"); const { v4: uuidv4 } = require("uuid"); const cors = require("cors"); const busboy = require("busboy"); let path = require("path"); let os = require("os"); let fs = require("fs"); let fields = {}; let fileData = {}; //========EXPRESS JS========== const app = express(); app.use(cors()) //========FIREBASE========== const serviceAccount = require("./serviceAccountKey.json"); const { useAttrs } = require("vue"); initializeApp({ credential: cert(serviceAccount), storageBucket: "website-1233f.appspot.com", }); const db = getFirestore(); const bucket = getStorage().bucket(); //========END POINTS======== app.get("/posts", (request, response) => { response.set("Access-Control-Allow-Origin", "*"); let posts = []; db.collection("posts") .orderBy("date", "desc") .get() .then((snapshot) => { snapshot.forEach((doc) => { posts.push(doc.data()); }); response.send(posts); }); console.log("posts=", posts); }); app.post("/createPost", (request, response) => { response.set("Access-Control-Allow-Origin", "*"); let token_id = uuidv4(); const bb = busboy({ headers: request.headers }); bb.on("file", (name, file, info) => { const { filename, encoding, mimeType } = info; let filepath = path.join(os.tmpdir(), filename); file.pipe(fs.createWriteStream(filepath)); fileData = { filepath, mimeType }; console.log( `File [${name}]: filename: %j, encoding: %j, mimeType: %j`, filename, encoding, mimeType ); file .on("data", (data) => { console.log(`File [${name}] got ${data.length} bytes`); }) .on("close", () => { console.log(`File [${name}] done`); }); }); bb.on("field", (name, val, info) => { console.log(`Field [${name}]: value: %j`, val); fields[name] = val; }); bb.on("close", () => { console.log("Done parsing form!"); bucket.upload( fileData.filepath, { uploadType: "media", metadata: { metadata: { contentType: fileData.mimeType, firebaseStorageDownloadTokens: token_id, }, }, }, (err, uploadedFile) => { if (!err) { createDocument(uploadedFile); } } ); // response.writeHead(303, { Connection: "close", Location: "/" }); function createDocument(uploadedFile) { db.collection("posts") .doc(fields.id) .set({ id: fields.id, caption: fields.caption, location: fields.location, date: parseInt(fields.date), imgUrl: `https://firebasestorage.googleapis.com/v0/b/${bucket.name}/o/${uploadedFile.name}?alt=media&token=${token_id}`, name: fields.name, }) .then((req, res) => { response.send("Post created"); }); } }); request.pipe(bb); }); app.delete("/deletePost/:id", (req, res) => { res.set("Access-Control-Allow-Origin", "*"); db.collection("posts").doc(req.params.id).delete(); res.send({ result: `Deleted post with id: ${req.params.id}` }); }); //========LOCALHOST LISTEN========== app.listen(3000);
内容的提问来源于stack exchange,提问作者Eric Andre
相关产品推荐
相关产品推荐

