Angular $http.delete CORS 错误(预检请求)

Posted

技术标签:

【中文标题】Angular $http.delete CORS 错误(预检请求)【英文标题】:Angular $http.delete CORS error (preflight request) 【发布时间】:2015-08-10 10:06:54 【问题描述】:

我有一个 Angular 应用 (v1.13.15) 和 Express.js(v4.12.4) 作为后端。

我的后端有一个 DELETE 方法,并且我已经启用了对它的 CORS 支持。

但是,当我使用 Angular $http.delete 时,我遇到了这个错误

请求的资源上不存在“Access-Control-Allow-Origin”标头。

我尝试过使用 Jquery,$.ajax() 调用它,我遇到了同样的问题!

我也试过用 POSTMAN 做 DELETE 请求,没有问题。

但是,使用我的 Angular 访问我的 GET 和 POST 方法没有问题..

我可以知道这是什么问题吗?

我的后端网址 http://localhost:3000

我使用 gulp-webserver 服务我的 AngularJS http://localhost:8000

我的服务器代码

exports.deleteGPSData = (req, res, next) => 
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

let id = req.params.id;

res.send('here');

还有我的 Angular 代码

$http.delete(API_URL + '/gps/' + id)
                .success(function(res) 
                    if (res.result !== 1) 
                        return defer.reject(new Error(id + ' failed to delete'));
                    

                    defer.resolve(res.id);
                )
                .error(function(status) 
                    defer.reject(status);
                );

我对 GET 和 POST 方法没有任何问题!只有当我使用 DELETE 方法时,我才遇到 CORS 错误!

我在下面附上了使用 Google Chrome 的请求标头的屏幕截图

下面是 Postman 的截图,

【问题讨论】:

尝试将res.header('Access-Control-Allow-Headers', 'X-Requested-With,content-type'); 更改为res.header('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type');,如果这有任何改变,请告诉我。 您也可以发布您的快递代码吗? @FrankerZ 我改了,还是出现了同样的问题。 @neolivz4ever 你想要哪一部分?我已经在这篇文章中发布了路由器中间件,如果你想要在中间件之前,那么它只是 app.delete('/gps/:id', routes.gps.deleteGPSData); @FrankerZ 更新了邮递员的截图 【参考方案1】:

我设法解决了这个问题,这是由于预检请求

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

在为DELETE做CORS时,会先向服务器发送一个OPTIONS方法,然后再解析为DELETE方法

所以它在后端,我应该有 OPTIONS 的路由,然后调用 next() 将它传递给 DELETE 方法

后端代码:

app.options('/gps/:id', routes.gps.optionGPSData);
app.delete('/gps/:id', routes.gps.deleteGPSData);

还有我的路由器中间件

exports.optionGPSData = (req, res, next) => 
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'DELETE');
res.header('Access-Control-Allow-Headers', 'X-Requested-With,Content-Type');

next();

POSTMAN 是否能够执行 DELETE 请求? (这是因为它向我的服务器发送 DELETE http 请求,而不是 OPTIONS),而在 Web 浏览器中,它将发送一个 OPTIONS 用于预检请求(这主要是出于安全考虑)

*对@FrankerZ大喊大叫,他让我比较POSTMAN和我的Chrome结果,然后我看到访问控制允许方法有差异,这导致我尝试使用cors中间件(https://www.npmjs.com/package/cors),它可以工作然后我设法解决了问题,这是由于预检请求!

【讨论】:

【参考方案2】:

您可以使用 cors npm 模块来启用跨域请求

https://www.npmjs.com/package/cors

【讨论】:

【参考方案3】:
app.options('/gps/:id', function(req, res)  res.json() );
app.delete('/gps/:id', routes.gps.optionGPSData);

您可以定义自己的选项回调(不必相同)。

【讨论】:

【参考方案4】:

预检请求仅发送标头而不发送标头值。因此,这会导致问题。

CORS 需要从客户端和服务器端处理。

我在 server.js 文件中添加了下面的标头设置(应用程序在 reactjs 中)

app.use(function(req, res, next) 
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Request-Headers", "*");
  res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With,X-HTTP-Method-Override, Content-Type, Accept, Authorization");
  res.header("Access-Control-Allow-Credentials", "true");
  next();
);

从服务器端我们也必须处理 CORS 请求。

以下是在服务器端 API 中所做的更改(应用程序在 java jersey 框架中)

app.use(function(req, res, next) 
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Request-Headers", "*");
  res.header('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With,X-HTTP-Method-Override, Content-Type, Accept, Authorization");
  res.header("Access-Control-Allow-Credentials", "true");
  next();
);

仅当我们尝试从不同来源连接到本地主机时才会出现此预检问题。

【讨论】:

以上是关于Angular $http.delete CORS 错误(预检请求)的主要内容,如果未能解决你的问题,请参考以下文章

在带有 Angular 的 Spring Boot 中启用了 Cors,但仍然出现 cors 错误

Angular CORS 请求被阻止

启用 CORS 时出现 Spring/Angular CORS 问题 [重复]

为啥只有 Angular 才会出现 CORS 错误? [复制]

即使在设置 CORS 标头和服务器响应之后,Angular 和 laravel 的 CORS 问题[重复]

如何在 Angular 5 的标头中添加 CORS 请求