为什么不在OPTIONS路由中添加CORS头允许浏览器访问我的API?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么不在OPTIONS路由中添加CORS头允许浏览器访问我的API?相关的知识,希望对你有一定的参考价值。

我试图在我的Node.js应用程序中支持使用Express.js Web框架的CORS。我已经阅读了a Google group discussion关于如何处理这个问题,并阅读了一些关于CORS如何工作的文章。首先,我这样做了(代码是用CoffeeScript语法编写的):

app.options "*", (req, res) ->
  res.header 'Access-Control-Allow-Origin', '*'
  res.header 'Access-Control-Allow-Credentials', true
  # try: 'POST, GET, PUT, DELETE, OPTIONS'
  res.header 'Access-Control-Allow-Methods', 'GET, OPTIONS'
  # try: 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept'
  res.header 'Access-Control-Allow-Headers', 'Content-Type'
  # ...

它似乎不起作用。好像我的浏览器(Chrome)没有发送初始OPTIONS请求。当我刚刚更新资源块时,我需要将跨源GET请求提交到:

app.get "/somethingelse", (req, res) ->
  # ...
  res.header 'Access-Control-Allow-Origin', '*'
  res.header 'Access-Control-Allow-Credentials', true
  res.header 'Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS'
  res.header 'Access-Control-Allow-Headers', 'Content-Type'
  # ...

它有效(在Chrome中)。这也适用于Safari。

我读过......

在实现CORS的浏览器中,每个跨源GET或POST请求前面都有一个OPTIONS请求,用于检查GET或POST是否正常。

所以我的主要问题是,为什么在我的案例中似乎没有发生这种情况?为什么我的app.options块没有被调用?为什么我需要在主app.get块中设置标题?

答案

要回答您的主要问题,如果POST或GET中包含任何非简单内容或标题,则CORS规范仅要求OPTIONS调用在POST或GET之前。

需要CORS pre-flight请求的内容类型(OPTIONS调用)是除以下内容之外的任何Content-Type:

  1. application/x-www-form-urlencoded
  2. multipart/form-data
  3. text/plain

除上述内容之外的任何其他内容类型都将触发飞行前请求。

至于标题,除以下内容之外的任何请求标题都会触发飞行前请求:

  1. Accept
  2. Accept-Language
  3. Content-Language
  4. Content-Type
  5. DPR
  6. Save-Data
  7. Viewport-Width
  8. Width

任何其他请求标头将触发飞行前请求。

因此,您可以添加自定义标头,例如:x-Trigger: CORS,这应该触发飞行前请求并点击OPTIONS块。

MDN Web API Reference - CORS Preflighted requests

另一答案

首先只需在项目中安装cors。将终端(命令提示符)和cd带到项目目录并运行以下命令:

npm install cors --save

然后获取server.js文件并更改代码以在其中添加以下内容:

var cors = require('cors');


var app = express();

app.use(cors());

app.use(function(req, res, next) {
   res.header("Access-Control-Allow-Origin", "*");
   res.header('Access-Control-Allow-Methods', 'DELETE, PUT, GET, POST');
   res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
   next();
});

这对我有用..

另一答案

这对我来说很有用,因为它在路线中很容易实现,我使用meanjs和它的工作正常,safari,chrome等。

app.route('/footer-contact-form').post(emailer.sendFooterMail).options(function(req,res,next){ 
        res.header('Access-Control-Allow-Origin', '*'); 
        res.header('Access-Control-Allow-Methods', 'GET, POST');
        res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
        return res.send(200);

    });
另一答案

前段时间,我遇到了这个问题所以我这样做是为了在我的nodejs app中允许CORS:

首先,您需要使用以下命令安装cors

npm install cors --save

现在将以下代码添加到您的应用程序启动文件中,如(app.js or server.js

var express = require('express');
var app = express();

var cors = require('cors');
var bodyParser = require('body-parser');

//enables cors
app.use(cors({
  'allowedHeaders': ['sessionId', 'Content-Type'],
  'exposedHeaders': ['sessionId'],
  'origin': '*',
  'methods': 'GET,HEAD,PUT,PATCH,POST,DELETE',
  'preflightContinue': false
}));

require('./router/index')(app);
另一答案

如果您想使控制器特定,您可以使用:

res.setHeader('X-Frame-Options', 'ALLOWALL');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'POST, GET');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');

请注意,这也将允许iframe。

另一答案

Express 4.2.0(编辑:似乎在4.3.0中不起作用)我最简单的解决方案是:

function supportCrossOriginScript(req, res, next) {
    res.status(200);
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Content-Type");

    // res.header("Access-Control-Allow-Headers", "Origin");
    // res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    // res.header("Access-Control-Allow-Methods","POST, OPTIONS");
    // res.header("Access-Control-Allow-Methods","POST, GET, OPTIONS, DELETE, PUT, HEAD");
    // res.header("Access-Control-Max-Age","1728000");
    next();
}

// Support CORS
app.options('/result', supportCrossOriginScript);

app.post('/result', supportCrossOriginScript, function(req, res) {
    res.send('received');
    // do stuff with req
});

我想做app.all('/result', ...)也会起作用......

另一答案

可以参考下面的代码相同。资料来源:Academind/node-restful-api

const express = require('express');
const app = express();

//acts as a middleware
//to handle CORS Errors
app.use((req, res, next) => { //doesn't send response just adjusts it
    res.header("Access-Control-Allow-Origin", "*") //* to give access to any origin
    res.header(
        "Access-Control-Allow-Headers",
        "Origin, X-Requested-With, Content-Type, Accept, Authorization" //to give access to all the headers provided
    );
    if(req.method === 'OPTIONS'){
        res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET'); //to give access to all the methods provided
        return res.status(200).json({});
    }
    next(); //so that other routes can take over
})
另一答案

除了其他人所说的,不要忘记,除非使用nodemon,否则您需要重新启动节点服务器才能使更改生效!

我个人一直在刷新我的浏览器习惯,忘记它是服务器端代码。

另一答案

使用Express Middleware对我来说很有用。如果您已经在使用Express,只需添加以下中间件规则即可。它应该开始工作。

app.all("/api/*", function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With");
  res.header("Access-Control-Allow-Methods", "GET, PUT, POST");
  return next();
});

app.all("/api/*", function(req, res, next) {
  if (req.method.toLowerCase() !== "options") {
    return next();
  }
  return res.send(204);
});

Reference

另一答案

在我的index.js中,我补充说:

app.use((req, res, next) => {
   res.header("Access-Control-Allow-Origin", "*");
   res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
   res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
   next();
}) 
另一答案

我发现使用npm请求包(https://www.npmjs.com/package/request)非常容易

然后我基于http://blog.javascripting.com/2015/01/17/dont-hassle-with-cors/这个帖子我的解决方案

'use strict'

const express = require('express');
const request = require('request');

let proxyConfig = {
    url : {
        base: 'http://servertoreach.com?id=',
    }
}

/* setting up and configuring node express server for the application */
let server = express();
server.set('port', 3000);


/* methods forwarded to the servertoreach proxy  */
server.use('/somethingElse', function(req, res)
{
    let url = proxyConfig.url.base + req.query.id;
    req.pipe(request(url)).pipe(res);
});


/* start the server */
server.listen(server.get('port'), function() {
    console.log('express server with a proxy listening on port ' + server.get('port'));
});
另一答案

我发现最简单的方法是使用node.js包cors。最简单的用法是:

var cors = require('cors')

var app = express()
app.use(cors())

当然,有很多方法可以根据您的需要配置行为;上面链接的页面显示了许多示例。

另一答案

这与Pat的答案类似,区别在于我用res.sendStatus(200)完成;而不是next();

代码将捕获方法类型OPTIONS的所有请求并发回access-control-headers。

app.options('/*', (req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
    res.header('Access-

以上是关于为什么不在OPTIONS路由中添加CORS头允许浏览器访问我的API?的主要内容,如果未能解决你的问题,请参考以下文章

django-cors-headers

添加 Restlet 2.3 CORS 的正确方法

AWS Api Gateway 仅在 OPTIONS 调用时不响应 CORS 标头

关于CORS

ZF2中的CORS POST请求变成OPTIONS请求

http响应头中的X-Frame-Options防止被frame