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

HTTP请求无Origin头引发CORS冲突的问题求助

CORS问题排查:请求缺失Origin字段导致跨域失败

问题概述

前端向后端发起请求时遭遇CORS冲突,经排查根源是HTTP请求头中缺少Origin字段。

项目环境

两个项目部署在同一服务器(公网IP:84.201.143.32),共用IP但域名不同:

项目1

  • Frontend(React.js):域名 place.nomoredomains.xyz
  • Backend(Node.js + Express + MongoDB):域名 api.place.nomoredomains.xyz

项目2

  • Frontend(React.js):域名 ypdiploma.nomoreparties.co
  • Backend(Node.js + Express + MongoDB):域名 api.ypdiploma.nomoreparties.co

Nginx配置(sites-available/default)

server {

      server_name api.place.nomoredomains.xyz;

   location / {
                proxy_pass http://localhost:3000;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
      }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/place.nomoredomains.xyz/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/place.nomoredomains.xyz/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {

      server_name place.nomoredomains.xyz;

      root /home/lexev/react-mesto-api-full-gha/frontend/build;

      location / {
        try_files $uri $uri/ /index.html;
      }

    listen 443 ssl; # managed by Certbot
     ssl_certificate /etc/letsencrypt/live/place.nomoredomains.xyz/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/place.nomoredomains.xyz/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}


server {

      server_name api.ypdiploma.nomoreparties.co;

      location / {
                proxy_pass http://localhost:3001;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
      }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/place.nomoredomains.xyz/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/place.nomoredomains.xyz/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {

      server_name ypdiploma.nomoreparties.co;

      root /home/lexev/ypdiploma/movies-explorer-frontend/build;

      location / {
        try_files $uri $uri/ /index.html;
      }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/place.nomoredomains.xyz/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/place.nomoredomains.xyz/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}


server {
    if ($host = place.nomoredomains.xyz) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


      listen 80;

      server_name place.nomoredomains.xyz;
    return 404; # managed by Certbot


}server {
    if ($host = api.place.nomoredomains.xyz) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


      listen 80;

      server_name api.place.nomoredomains.xyz;
    return 404; # managed by Certbot


}

server {
    if ($host = ypdiploma.nomoreparties.co) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


      listen 80;

      server_name ypdiploma.nomoreparties.co;
    return 404; # managed by Certbot


}


server {
    if ($host = api.ypdiploma.nomoreparties.co) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


      listen 80;

      server_name api.ypdiploma.nomoreparties.co;
    return 404; # managed by Certbot


}

问题表现

  • 项目1的HTTP请求正常携带Origin头,无CORS问题
  • 项目2的HTTP请求未携带Origin头,触发CORS错误,错误提示为:No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://ypdiploma.nomoreparties.co' is therefore not allowed access.

相关代码

CORS中间件代码

const allowedCors = [
  'https://ypdiploma.nomoreparties.co',
  'http://ypdiploma.nomoreparties.co',
  'https://ypdiploma.nomoreparties.co/',
  'http://ypdiploma.nomoreparties.co/',
  'http://localhost:3000',
];

const corsHandler = (req, res, next) => {
  const { origin } = req.headers;
  const { method } = req;

  const DEFAULT_ALLOWED_METHODS = 'GET,HEAD,PUT,PATCH,POST,DELETE';
  const requestHeaders = req.headers['access-control-request-headers'];

  if (allowedCors.includes(origin)) {
    res.header('Access-Control-Allow-Origin', origin);
    res.header('Access-Control-Allow-Credentials', true);
  }

  if (method === 'OPTIONS') {
    res.header('Access-Control-Allow-Methods', DEFAULT_ALLOWED_METHODS);
    res.header('Access-Control-Allow-Headers', requestHeaders);
    res.header('Access-Control-Allow-Credentials', true);
    return res.end();
  }

  return next();
};

module.exports = { corsHandler };

后端应用入口代码

require('dotenv').config();
const express = require('express');
const mongoose = require('mongoose');
const cookieParser = require('cookie-parser');
const { errors } = require('celebrate');
const helmet = require('helmet');
const { requestLogger, errorLogger } = require('./middlewares/logger');
const { corsHandler } = require('./middlewares/cors');
const { limiter } = require('./middlewares/limiter');

const errorHandler = require('./middlewares/errorHandler');
const { MONGOOSE_DB } = require('./constants/constants');

const { PORT = 3001 } = process.env;

const app = express();
mongoose.connect(MONGOOSE_DB);

app.use(helmet());
app.use(corsHandler);
app.use(express.json());
app.use(cookieParser());
app.use(requestLogger);

app.use('/', limiter, require('./routes/index'));

app.use(errorLogger);

app.use(errors());
app.use(errorHandler);

app.listen(PORT);

前端Fetch代码

class MainApi {
  constructor() {
    this._baseUrl = 'https://api.ypdiploma.nomoreparties.co'
    this._headers = {
      'Content-Type': 'application/json',
    };
  }

  _getResponseData(res) {
    if (res.ok) {
      return res.json();
    } else {
      return Promise.reject(res);
    }
  }

  getUserinfo() {
    return fetch(this._baseUrl + '/users/me', {
      headers: this._headers,
      credentials: 'include',
    }).then((res) => this._getResponseData(res));
  }
}

const mainApi = new MainApi();

export default mainApi;

排查尝试

曾尝试通过Referer头做CORS校验,但未解决问题;怀疑问题出在Nginx配置中,但无法准确定位,寻求解决方案。

内容的提问来源于stack exchange,提问作者AlexCap

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:32:03