ExpressJS Post 方法 - 无访问控制允许来源

Posted

技术标签:

【中文标题】ExpressJS Post 方法 - 无访问控制允许来源【英文标题】:ExpressJS Post Method - No Access-Control-Allow-Origin 【发布时间】:2018-03-18 07:27:43 【问题描述】:

我一直在阅读我发现的所有关于 CORS 的文章,但我仍然无法解决这个问题 - 没有“Access-Control-Allow-Origin”。

我需要使用 jquery ajax 向我的 node/expressjs 服务器发出 发布请求,但我无法让它工作。

这是我的 ajax 代码:

$.ajax(
    url: 'http://mydevserver:3000/api/nnnn',
    type: "POST",
    data: data,
    contentType: "application/json",
    async: true,
    success: function(data) 
        console.log("success!");
    
);

这是我设置响应头的 expressJS 部分:

var corsOrigin  ;

if (process.env.NODE_ENV == 'production') 
   console.log('Adding CORS to the headers...');
   corsOrigin = 'myprodserver';

else 
  corsOrigin = 'http://mydevserver:4200';



app.use(function(req, res, next) 
  res.set("Access-Control-Allow-Origin", corsOrigin);
  res.set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  res.set('Access-Control-Allow-Methods', 'POST, GET, PUT, PATCH, DELETE, OPTIONS');

  next();

);

我在这里缺少什么?我用完了选项...

非常感谢您的帮助!

我最诚挚的问候。

更新 1 - 完整的服务器和路由代码

server.js

var http = require('http');
var app = require('./app');

/**
 * Get port from environment and store in Express.
 */

console.log('Server port set to ' + process.env.NODE_PORT);
var port = normalizePort(process.env.NODE_PORT || '3000');
app.set('port', port);

/**
 * Create HTTP server.
 */

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) 
    var port = parseInt(val, 10);

    if (isNaN(port)) 
        // named pipe
        return val;
    

    if (port >= 0) 
        // port number
        return port;
    

    return false;


/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) 
    if (error.syscall !== 'listen') 
        throw error;
    

    var bind = typeof port === 'string'
        ? 'Pipe ' + port
        : 'Port ' + port;

    // handle specific listen errors with friendly messages
    switch (error.code) 
        case 'EACCES':
            console.error(bind + ' requires elevated privileges');
            process.exit(1);
            break;
        case 'EADDRINUSE':
            console.error(bind + ' is already in use');
            process.exit(1);
            break;
        default:
            throw error;
    


/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() 
    var addr = server.address();
    var bind = typeof addr === 'string'
        ? 'pipe ' + addr
        : 'port ' + addr.port;
    console.log('Listening on ' + bind);

app.js

var express = require('express');
var path = require('path');
var AWS = require("aws-sdk");
var app = express();
var bodyParser = require('body-parser');

var fs = require('fs');

var cors = require("cors");

app.use(bodyParser.json(limit: '50mb'));
app.use(bodyParser.urlencoded(limit: 150000000, extended: true, parameterLimit:50000));

var corsOrigin  ;

if (process.env.NODE_ENV == 'production') 
   console.log('Adding CORS to the headers...');
   corsOrigin = 'prodserver';

else 
  corsOrigin = 'http://localhost:4200';



app.use(function(req, res, next) 
    res.setHeader('Access-Control-Allow-Origin', corsOrigin);
    res.setHeader("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT,DELETE");
    res.set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
    res.set('Access-Control-Allow-Credentials', 'true');
    next();
);



var globSync          = require('glob').sync;
var routes            = globSync('./routes/*.js',  cwd: __dirname).map(require);


AWS.config.update(
  region: "xxxx",
  accessKeyId: "xxxx",
  secretAccessKey: "xxxxxxx"
);

var ddb = new AWS.DynamoDB.DocumentClient();

routes.forEach( function(route)  
    route(app, ddb);
);

app.use('/', express.static(path.join(__dirname, 'dist')));

app.use('/api/resources', express.static(path.join(__dirname, 'resources')));


module.exports = app;

【问题讨论】:

我建议使用这个模块。 github.com/expressjs/cors它将为您设置一切。 @MykolaBorysyuk 我也试过那个。也不走运。感谢您的帮助。 你确定你试过了吗?像 app.use(cors(corsOptions));您可以从 cors wiki 获得 corsOptions。因为我在生产中使用相同的模块并且从来没有任何问题。但没问题。希望你能找到答案。 顺便说一句...你能发布所有 expressJs 部分和节点服务器的代码吗? @MykolaBorysyuk 刚刚用完整代码更新了问题。 【参考方案1】:

正如 sideshowbarker 所指出的,我在 ajax 调用中传递了 contentType: "application/json"。这就是问题所在。以下是工作代码:

$.ajax(
    url: 'http://mydevserver:3000/api/nnnn',
    type: "POST",
    data: data,
    async: true,
    success: function(data) 
        console.log("success!");
    
);

感谢大家的帮助!

【讨论】:

【参考方案2】:

在 express 节点中这样尝试:

var origin = "http://localhost:4200";
app.use(function(req, res, next) 
    res.header('Access-Control-Allow-Origin', origin || "*");
    res.header('Access-Control-Allow-Methods', 'GET,POST,PUT,HEAD,DELETE,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'content-Type,x-requested-with');
    next();
);

【讨论】:

感谢您的帮助,但我仍然遇到同样的问题:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'localhost:4200' 不允许访问。响应的 HTTP 状态代码为 400。 试试这个 res.setHeader('Access-Control-Allow-Origin', '*');而不是特定的来源 同样的结果,钱德鲁。 @Marrone 尝试上述方法,但在 app.use(function(req, res, next) 行之前添加 app.options('*', cors())。这样就可以支持 CORS 预检 OPTIONS 请求。 @sideshowbarker 仍然遇到同样的问题:无法加载 localhost:3000/api/xxxx:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,不允许访问 Origin 'localhost:4200'。响应的 HTTP 状态代码为 400。

以上是关于ExpressJS Post 方法 - 无访问控制允许来源的主要内容,如果未能解决你的问题,请参考以下文章

如何允许无限制的发布请求 expressjs

ExpressJS SyntaxError:意外的令牌 C

AngularJS + ExpressJS。代理 POST 请求待处理

http协议。会话控制cookie

Expressjs在POST请求后不发送响应

春季网关请求被 CORS 阻止(无访问控制-允许-来源标头)