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
相关产品推荐
相关产品推荐

