尽管服务器端文件中存在域名,但仍被 CORS 策略阻止

问题描述 投票:0回答:1

我遇到了一个非常奇怪的问题,即使经过数小时的故障排除,这个问题仍然存在。

项目背景

首先,我的前端运行在 React+Vite 上(但我并没有真正使用任何与 Vite 相关的东西),托管在 Vercel 上,比如说,https://mywebsite.ca

我的后端在 Express 和 Node 上运行,也托管在 Vercel 上,https://backend.vercel.app

我的 MySQL 数据库托管在 AWS RDS 上

问题

问题是登录或注册页面的所有内容都正常(有时它说不是服务器错误,但这种情况非常罕见)。在此阶段我没有遇到任何 CORS 问题。 然而,当用户登录时(引导我访问 https://mywebsite.ca/course-selection),我遇到了 CORS 问题。

我很确定我的 CORS 都定义良好,您可以在我的 index.js 中看到:

import express from "express"
import cors from "cors"
import userRoutes from "./routes/users.js"
import authRoutes from "./routes/auth.js"
import courseChangeRoutes from "./routes/courseChange.js"
import cookieParser from "cookie-parser";


const app = express();
app.use(express.json());
app.use(cookieParser());

app.use(
    cors({
      origin: 'https://www.mywebsite.ca/',
      methods: ['GET', 'POST', 'OPTIONS', 'PUT', 'DELETE'],
      credentials: true,
    })
);

app.use((req, res, next) => {
  res.header("Access-Control-Allow-Credentials", true);
  next();
});

app.use("/backend/users", userRoutes);
app.use("/backend/auth", authRoutes);
app.use("/backend/courseChange", courseChangeRoutes);

我什至添加了选项,因为我做了一些研究,发现有时预检请求是使用选项发出的。然而问题仍然存在,我仍然经常收到: 从源“https://www.mywebsite.ca”访问“https://backend.vercel.app/backend/courseChange/”处的 XMLHttpRequest 已被 CORS 策略阻止:无“Access-Control-Allow-Origin”标头存在于所请求的资源上。 然后接着是 加载资源失败:net::ERR_FAILED

可能有助于故障排除的其他相关文件

/operation/courseChange.js:(后端)


export const courseChange = async (req, res) => {
    const { userId, courses_ids, term } = req.body;

    if (!userId || !Array.isArray(courses_ids) || !term) {
        return res.status(400).send('Invalid input');
    }

    const maxCourses = 15; 

    try {
        // Clear existing courses for the specified term
        let clearQuery = 'UPDATE users SET ';
        for (let i = 1; i <= maxCourses; i++) {
            clearQuery += `${term}Course${i} = NULL, `;
        }
        clearQuery = clearQuery.slice(0, -2) + ' WHERE id = ?';
        console.log('Clear Query:', clearQuery, [userId]);
        await db.execute(clearQuery, [userId]);

        // Construct the update query for new courses
        let updateQuery = 'UPDATE users SET ';
        const updateValues = [];
        if (courses_ids.length > 0) {
            courses_ids.forEach((courseId, index) => {
                updateQuery += `${term}Course${index + 1} = ?, `;
                updateValues.push(courseId);
            });
            updateQuery = updateQuery.slice(0, -2);
            updateQuery += ' WHERE id = ?';
            updateValues.push(userId);


            console.log('Update Query:', updateQuery, updateValues);
            await db.execute(updateQuery, updateValues);
            res.status(200).send('Courses updated successfully');
            }

    } catch (error) {
        console.error('Error updating courses:', error);
        res.status(500).send('Error updating courses: ' + error.message);
    }
    
};

/pages/course-selection.jsx:(前端)

import { useState, useEffect } from 'react';
import LeftMenu from '/src/components/leftMenu';
import Calendar from '/src/components/calendar';
import Nav from '/src/components/nav';
import Selection from '/src/components/selections';
import fallJSON from '/src/assets/fall_2024_0626.json';
import winterJSON from '/src/assets/winter_2025_0626.json';
import axios from 'axios'

axios.defaults.withCredentials = true;


export default function Courses() {

    const [fallCourses, setFallCourses] = useState([]);
    const [winterCourses, setWinterCourses] = useState([]);
    const [fallData, setFallData] = useState(fallJSON);
    const [winterData, setWinterData] = useState(winterJSON);
    const [err, setError] = useState(null);

    const updateFallCourses = async (courses_ids) => {
        // Prepare for Calendar Rendering
        const courses = courses_ids.flatMap(course => fallData[course].slice(2));
        setFallCourses(courses);
        // Send data to backend
        const user = JSON.parse(localStorage.getItem('user'));
        const userId = user ? user.id : null;
        const term = "fall"
        try {
            await axios.post('https://backend.vercel.app/backend/courseChange/', {
                userId,
                courses_ids,
                term,
            }, {
                headers: {
                    'Access-Control-Allow-Origin': '*',
                    'Content-Type': 'application/json',
                }
            });
            console.log('Courses updated successfully');
        } catch (err) {
            const errorMessage = err.response?.data?.message || "An unexpected error occurred";
            setError(errorMessage);
        }

    };

// There's also const updateWinterCourses right here that basically is the same code

context/authContext.jsx(处理登录注销,完全有效)

import axios from "axios";
import { createContext, useEffect, useState } from "react";

export const AuthContext = createContext();

export const AuthContextProvider = ({ children }) => {
  const [currentUser, setCurrentUser] = useState(
    JSON.parse(localStorage.getItem("user")) || null
  );

  const login = async (inputs) => {
    const res = await axios.post("https://backend.vercel.app/backend/auth/login", inputs, {
      withCredentials: true,
    });

    setCurrentUser(res.data)
  };

  const logout = async () => {
    await axios.post("https://backend.vercel.app/backend/auth/logout", {}, {
      withCredentials: true
    });
    setCurrentUser(null);
  };

  useEffect(() => {
    localStorage.setItem("user", JSON.stringify(currentUser));
  }, [currentUser]);

  return (
    <AuthContext.Provider value={{ currentUser, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
};

不可预测的行为

最后,一些意想不到的事情,在调用函数 updateFallCourses 时,可能会发生以下情况之一:

  1. CORS 和 ERR 错误被打印到控制台,没有任何反应
  2. 没有出现 CORS 和 ERR 错误我收到一条消息“课程已成功更新”并且数据库已更新
  3. 就像2一样,没有错误,成功消息,但数据库没有更新。

我尝试过的方法包括:允许连接index.js中的所有OPTIONS请求,但这并没有解决我的问题。另外,如果重要的话,当我在 http://localhost:8800 上运行后端并在 http://localhost:3000 上运行前端时,一切都会非常顺利,没有任何 CORS 问题(显然当时 CORS 中定义的源将是 localhost: 3000)。

我真的被困住了,希望在一两天内启动该网站。这是最后一步,因为无法更新用户对数据库的更改,我错过了最重要的功能。我将不胜感激任何建议!由于这是我的第一个全栈项目,如果您有有关如何管理不同端的相关提示,或者是否可以以更简洁的方式编写一些代码,我也将不胜感激!谢谢!!

reactjs node.js express server cors
1个回答
0
投票

您遇到的问题似乎与 CORS 设置有关,或者可能与处理您的请求的方式存在一些不一致有关。

以下是基于您的代码的建议,可帮助您排除故障并解决问题。

CORS 配置看起来正确,一个小问题是原始设置,它不应在原始 URL 中包含尾部斜杠。

app.use(
    cors({
      origin: 'https://www.mywebsite.ca', // Remove trailing slash
      methods: ['GET', 'POST', 'OPTIONS', 'PUT', 'DELETE'],
      credentials: true,
    })
);

向日志标头添加一个中间件,这将帮助您查看响应是否具有正确的 CORS 标头,

app.use((req, res, next) => {
  res.header("Access-Control-Allow-Credentials", true);
  res.header("Access-Control-Allow-Origin", "https://www.mywebsite.ca"); // Explicitly set the allowed origin
  res.header("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
  console.log(`CORS headers set for ${req.method} ${req.url}`);
  next();
});

确保服务器处理预检选项请求,

app.options('*', (req, res) => {
  res.sendStatus(200);
});

updateFallCourses
函数中,不要设置
Access-Control-Allow-Origin
标头,删除该标头并仅保留 Content-Type

headers: {
            'Content-Type': 'application/json',
        }

Vercel 可能对处理 CORS 有一些特定的要求或设置。确保没有特定于平台的问题导致问题。

使用 Postman 等工具模拟对后端的请求并检查标头和响应。

通过执行以下步骤并确保所有配置设置正确,您应该能够诊断并修复 CORS 问题。

© www.soinside.com 2019 - 2024. All rights reserved.