angular 部署在具有节点快递后端的 heroku 上的应用程序的 CORS 预检请求错误

CORS preflight request error on angular app deployed on heroku with node express backend

我已经为学校的一个项目在 heroku 上部署了一个 angular 应用程序(前端和后端分离在多个 heroku 应用程序中),但我遇到了 CORS 预检请求的问题。

每次我向后端发送请求时都会收到以下错误

Access to XMLHttpRequest at 'https://playlist-manager-backend.herokuapp.com/user/authenticate' from origin 'https://playlist-manager-admin.herokuapp.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

这是我的 server.js 推送到后端应用程序 (playlist-manager-backend)

的代码
const express = require("express");
const { connect: dbconnect } = require("./src/db");
const { apiPort } = require("./src/config");
const routes = require("./src/routes");
const bodyParser = require("body-parser");
// Connect to the database
dbconnect();

// Create the server
const app = express();

// const cookieParser = require("cookie-parser");
// app.use(cookieParser());
app.use(bodyParser.json({ limit: "5mb" }));
// app.get("/", (req, res) => res.send("Hello World"));
const cors = require("cors");

/*let whitelist = ["https://playlist-manager-admin.herokuapp.com/","https://playlist- manager-user.herokuapp.com/"];*/

const corsOptions = {
    origin: ["https://playlist-manager-admin.herokuapp.com/", "https://playlist-manager-user.herokuapp.com/"],
    preflightContinue:false,
    credentials: true
}

app.use(cors(corsOptions));


app.use("/", routes);
app.use(express.static("./adverts"));

app.listen(apiPort, () => {
    console.log(`Server is listening on port ${apiPort}`);
});

后端函数的路由在 routes.js 文件中使用路由器定义,如下所示。

const express = require("express");
const router = express.Router();

const userRoute = require("../user/user.route");
const playlistRoute = require("../playlist/playlist.route");
const videoRoute = require("../video/video.route");
const annonceUploadRoute = require("../annoncesUpload/annoncesUpload.route");
const historyRoute = require("../history/history.route");
const advertiserRoute = require("../advertiser/advertiser.route");

router.use("/user", userRoute);
router.use("/playlist", playlistRoute);
router.use("/video", videoRoute);
router.use("/annoncesUpload", annonceUploadRoute);
router.use("/history", historyRoute);
router.use("/annonceur", advertiserRoute);

module.exports = router;

下面是一个如何实现路由的例子:

router.post("/getById", async function(req, res) {
     const request = {
         _id: req.body._id,
     };
     const result = await bo.getById(request);
     res.send(result);
});

前端使用如下实现的服务向后端发送 post 请求:

import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';

export interface BackendData {
  success: string ;
  data: any ;
}

@Injectable({
  providedIn: 'root'
})
export class MessageService {

  constructor(private http:HttpClient) { }

  sendMessage(Url:string, data:any): Observable<BackendData> {
    const serveur = environment.server + Url ;
    
    return this.http.post<BackendData>(
      serveur,
      data,
      {withCredentials: true}
    );
  }
}

我尝试了我在网上看到的所有解决方案,但总是遇到相同的错误或与 CORS 策略相关的其他错误。 我需要帮助来弄清楚这种行为。 当我像文档中那样使用 cors 包指定 localhost 时,该应用程序在本地运行良好。

编辑: 我删除了 URL 上的斜杠,我的 server.js 是这样的:

const express = require("express");
const { connect: dbconnect } = require("./src/db");
const { apiPort } = require("./src/config");
const routes = require("./src/routes");
const bodyParser = require("body-parser");
// Connect to the database
dbconnect();

// Create the server
const app = express();

// const cookieParser = require("cookie-parser");
// app.use(cookieParser());
app.use(bodyParser.json({ limit: "5mb" }));
// app.get("/", (req, res) => res.send("Hello World"));
const cors = require("cors");

/*let whitelist = ["https://playlist-manager-admin.herokuapp.com/", "https://playlist-manager-user.herokuapp.com/"];*/

const corsOptions = {
  origin: ["https://playlist-manager-admin.herokuapp.com", "https://playlist-manager-user.herokuapp.com"],
  credentials: true
}

app.use(cors(corsOptions));


app.use("/", routes);
app.use(express.static("./adverts"));

app.listen(apiPort, () => {
    console.log(`Server is listening on port ${apiPort}`);
});

This is the network tab after sending the request

This is the xhr request shown in the network tab

This is the preflight request in the network tab

感谢 jubObs 的评论,我设法解决了这个问题。问题的根源是后端服务器没有启动,这导致了 503 状态。我忘记添加定义数据库连接凭据的文件,这导致后端在添加 headers.

之前失败

这是新的 server.js 代码:

const express = require("express");
const { connect: dbconnect } = require("./src/db");
const { apiPort } = require("./src/config");
const routes = require("./src/routes");
const bodyParser = require("body-parser");
// Connect to the database
dbconnect();

// Create the server
const app = express();

// const cookieParser = require("cookie-parser");
// app.use(cookieParser());
app.use(bodyParser.json({ limit: "5mb" }));
// app.get("/", (req, res) => res.send("Hello World"));
const cors = require("cors");

/*let whitelist = ["https://playlist-manager-admin.herokuapp.com/", "https://playlist-manager-user.herokuapp.com/"];*/

const corsOptions = {
   origin: ["https://playlist-manager-admin.herokuapp.com", "https://playlist-manager-user.herokuapp.com"],
   credentials: true
}

app.use(cors(corsOptions));


app.use("/", routes);
app.use(express.static("./adverts"));

app.listen(apiPort, () => {
   console.log(`Server is listening on port ${apiPort}`);
});

数据库连接正在使用 dotenv 并且定义数据库凭据的 .env 文件不在主分支中,所以我推送了它。 为了解决这个问题,我检查了 heroku 上的应用程序日志,它们位于“更多”和“查看日志”中。