You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 19:55:19