NodeJS + ExpressJS:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段

Posted

技术标签:

【中文标题】NodeJS + ExpressJS:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段【英文标题】:NodeJS + ExpressJS: Request header field not allowed by Access-Control-Allow-Headers in preflight response 【发布时间】:2017-02-20 16:12:56 【问题描述】:

我目前有一个 NodeJS + ExpressJS 作为客户端服务器,向后端服务器发出 API 请求。当我发出 API 请求时,我收到以下错误:

Request header field firstname is not allowed by Access-Control-Allow-Headers in preflight response.

我尝试了一切以允许 CORS,但我仍然遇到同样的错误。这是我的 NodeJS + ExpressJS 客户端服务器的设置方式:

    var express = require('express');
    var cors = require('cors');
    var path = require('path');
    var config = require('../webpack.config.js');
    var webpack = require('webpack');
    var webpackDevMiddleware = require('webpack-dev-middleware');
    var webpackHotMiddleware = require('webpack-hot-middleware');
    var app = express();
    var compiler = webpack(config);
    
    app.use(cors());
    
    app.use(webpackDevMiddleware(compiler, noInfo: true, publicPath: config.output.publicPath));
    
    app.use(webpackHotMiddleware(compiler));
    
    app.use(express.static('./dist'));
    
    app.use('/', function (req, res) 
      res.header("Access-Control-Allow-Origin", "*");
      res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
      res.sendFile(path.resolve('client/index.html'))
    )
    
    var port = 3000;
    
    app.listen(port, function(error) 
      if (error) throw error;
      console.log("Express server listening on port", port);
    );

可能是什么问题?目前唯一可行的方法是下载 https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en 并启用它,然后我不会收到错误消息,API 请求会成功。

编辑 - 我如何发出 API 请求

  logInUser(userCredentials) 

    var userCredsBody = 
        'firstname': `$userCredentials.username`,
        'password': `$userCredentials.password`
    

    var configuration = 
      method: 'POST',
      headers: 
        'Content-Type': 'application/json'
      ,
      body: JSON.stringify(userCredsBody)
    

    return function(dispatch) 
      fetch('https://serverapi.com:8080/userInfo', configuration)
      .then(response => response.json())
      .then(response => 
        console.log('Successful and ', response)
      )
      .catch((error) => 
        console.log("Error: ", error)
      )
    

【问题讨论】:

【参考方案1】:

更改标题顺序。

使用这样的东西:

var express = require('express');
//This is not longer required, unless you want to disable CORS
//var cors = require('cors');
var path = require('path');
var bodyParser = require('body-parser');
var config = require('../webpack.config.js');
var webpack = require('webpack');
var webpackDevMiddleware = require('webpack-dev-middleware');
var webpackHotMiddleware = require('webpack-hot-middleware');
var app = express();
var compiler = webpack(config);
//The same, no longer required
//app.use(cors());

app.use(webpackDevMiddleware(compiler, noInfo: true, publicPath: config.output.publicPath));

app.use(webpackHotMiddleware(compiler));

app.use(express.static('./dist'));
//Add bodyParser to parse all body as JSON
app.use(bodyParser.json());
app.use(bodyParser.urlencoded(extended: true));

function setupCORS(req, res, next) 
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'X-Requested-With, Content-type,Accept,X-Access-Token,X-Key');
    res.header('Access-Control-Allow-Origin', '*');
    if (req.method === 'OPTIONS') 
        res.status(200).end();
     else 
        next();
    

app.all('/*', setupCORS);

app.use('/', function (req, res) 
    res.sendFile(path.resolve('client/index.html'))
);

var port = 3000;

app.listen(port, function(error) 
    if (error) throw error;
    console.log("Express server listening on port", port);
);

现在您有一个为每个请求设置 CORS 的中间件。

如果你想在单条路由上禁用/启用 cors,也许你需要更改

app.all('/*', setupCORS);

仅用于您要使用 CORS 配置设置的路由。

我加了body-parser middleware.

【讨论】:

抱歉,在我接受答案并投票之前,你能和我一起展示完整的代码吗?我知道顺序很重要,所以要确保我以正确的顺序设置它们 @JoKo 我制作并编辑并包含所有代码。 setupCORS 应该包含在之前路线 顺便说一句,除非你想更严格地控​​制应用中的路由和响应,否则你应该避免我的方法并检查 CORS 模块配置。我喜欢我的函数,因为它易于实现并且没有外部依赖。 @感谢更新,我尝试了一下,但我仍然收到错误:Fetch API cannot load https://serverapi.com:8080/userInfo. Request header field userfirstname is not allowed by Access-Control-Allow-Headers in preflight response.Error: TypeError: Failed to fetch(…)。为了澄清起见,https://serverapi.com:8080 是后端 API 服务器 URL。 @JoKo 你是如何提出请求的?也许问题出在内容类型上。您使用的是角度还是jquery?看看这个回复:***.com/a/30554385/1757214

以上是关于NodeJS + ExpressJS:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段的主要内容,如果未能解决你的问题,请参考以下文章

无法加载“端点”:预检响应中的 Access-Control-Allow-Headers 不允许请求标头字段 If-Modified-Since

从 Angular/NodeJS/ExpressJS 向 3rd 方 URL 的 POST 请求

Expressjs /在passportjs响应之前更改标题

异步和递归目录扫描,用于 Nodejs 和 Expressjs 中的文件列表

在 ExpressJS 响应中返回异步等待 try/catch 抛出错误 [重复]

我们如何使用带有 expressjs-nodejs 的 mongoose 对 mongodb 中的 ObjectId 列执行排序?