Angularjs 如何跳过选项飞行前请求?

Angularjs 如何跳过选项飞行前请求?,angularjs,post,cors,preflight,Angularjs,Post,Cors,Preflight,我开发了一个PhoneGap应用程序,现在正在转化为一个移动网站。除了一个小故障外,一切都很顺利。我通过POST请求使用某个第三方API,该API在应用程序中运行良好,但在移动网站版本中失败 仔细观察之后,看起来AngularJS(我猜实际上是浏览器)首先发送了一个选项请求。今天我学到了很多关于CORS的知识,但我似乎不知道如何完全禁用它。我没有访问该API的权限(因此不可能在该端进行更改),但他们已将我正在处理的域添加到其access Control Allow Origin头中 这就是我所说

我开发了一个PhoneGap应用程序,现在正在转化为一个移动网站。除了一个小故障外,一切都很顺利。我通过POST请求使用某个第三方API,该API在应用程序中运行良好,但在移动网站版本中失败

仔细观察之后,看起来AngularJS(我猜实际上是浏览器)首先发送了一个选项请求。今天我学到了很多关于CORS的知识,但我似乎不知道如何完全禁用它。我没有访问该API的权限(因此不可能在该端进行更改),但他们已将我正在处理的域添加到其access Control Allow Origin头中

这就是我所说的代码:

        var request = {
                language: 'fr',
                barcodes: [
                    {
                        barcode: 'somebarcode',
                        description: 'Description goes here'
                    }
                ]
            };
        }
        var config = {
            headers: { 
                'Cache-Control': 'no-cache',
                'Content-Type': 'application/json'
            }
        };
        $http.post('http://somedomain.be/trackinginfo', request, config).success(function(data, status) {
            callback(undefined, data);
        }).error(function(data, status) {
            var err = new Error('Error message');
            err.status = status;
            callback(err);
        });
如何防止浏览器(或AngularJS)发送该选项请求而直接跳到实际的POST请求?我正在使用AngularJS 1.2.0


提前感谢。

预飞行由您的
应用程序/json
内容类型触发。防止这种情况发生的最简单方法是在您的案例中将内容类型设置为
text/plain
application/x-www-form-urlencoded
&
多部分/表单数据
内容类型也是可以接受的,但是您当然需要适当地设置请求负载的格式

如果您在进行此更改后仍然看到飞行前,那么Angular可能也会向请求添加一个X头

或者您可能有将触发它的标头(授权、缓存控制…),请参阅:


正如Ray所说,您可以通过修改内容标题来阻止它,如-

 $http.defaults.headers.post["Content-Type"] = "text/plain";
例如—

angular.module('myApp').factory('User', ['$resource','$http',
    function($resource,$http){
        $http.defaults.headers.post["Content-Type"] = "text/plain";
        return $resource(API_ENGINE_URL+'user/:userId', {}, {
            query: {method:'GET', params:{userId:'users'}, isArray:true},
            getLoggedIn:{method:'GET'}
        });
    }]);
或者直接打电话-

var req = {
 method: 'POST',
 url: 'http://example.com',
 headers: {
   'Content-Type': 'text/plain'
 },
 data: { test: 'test' }
}

$http(req).then(function(){...}, function(){...});
这不会发送任何飞行前选项请求


注意:请求不应具有任何自定义标头参数,如果请求标头包含任何自定义标头,则浏览器将发出飞行前请求,您无法避免。

当执行某些类型的跨域AJAX请求时,支持CORS的现代浏览器将插入额外的“飞行前”请求以确定他们是否具有执行该操作的权限。 从示例查询:

$http.get( ‘https://example.com/api/v1/users/’ +userId,
  {params:{
           apiKey:’34d1e55e4b02e56a67b0b66’
          }
  } 
);
作为这个片段的结果,我们可以看到地址被发送了两个请求(OPTIONS和GET)。来自服务器的响应包括确认查询获取权限的头。如果服务器未配置为正确处理选项请求,则客户端请求将失败。例如:

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: accept, origin, x-requested-with, content-type
Access-Control-Allow-Methods: DELETE
Access-Control-Allow-Methods: OPTIONS
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Methods: GET
Access-Control-Allow-Methods: POST
Access-Control-Allow-Orgin: *
Access-Control-Max-Age: 172800
Allow: PUT
Allow: OPTIONS
Allow: POST
Allow: DELETE
Allow: GET

将内容类型设置为undefined将使javascript按原样传递头数据,并重写默认的$httpProvider头配置


我认为最好的方法是检查请求是否属于“选项”类型,并从中间件返回200。这对我有用

express.use('*',(req,res,next) =>{
      if (req.method == "OPTIONS") {
        res.status(200);
        res.send();
      }else{
        next();
      }
    });

Preflight是由浏览器实现的web安全功能。对于Chrome,您可以通过添加--disable web security标志来禁用所有web安全性


例如:“C:\Program Files\Google\Chrome\Application\Chrome.exe”--禁用web安全--用户数据目录=“C:\newChromeSettingsWithoutSecurity”。您可以先创建一个新的chrome快捷方式,转到它的属性,然后如上所述更改目标。这应该有帮助

这是正确的答案——您的内容类型和缓存控制头正在触发飞行前请求。内容类型为text/plain的纯GET和其他几种方法是触发非预飞请求的唯一方法。请参阅:啊,是的,忘记了缓存控制。自定义标头也会触发预飞行。更改内容类型以防止选项测试不是答案。内容类型应与内容类型Regardles匹配如果它是浏览器抛出的,并且在后端,Http方法选项被阻止,它是否会产生任何效果,比如浏览器将不会调用相应的API进行POST/PUT as选项失败?我应该如何仅使用
$Http
?谢谢,这与我所做的类似。唯一的更改是方法
GET
和额外的头
Authorization
。但是仍然在发送飞行前的信息。你能把你的请求粘贴到这里吗?像卷发什么的?可能是因为授权头,请尝试删除它,然后重试。如果您发送自定义标题,angular将发送飞行前请求。第一个是对$http的请求,第二个是一个有效的请求,由postman构建:)你不能指望OP告诉他的客户端关闭浏览器安全只是为了启用一个功能,对吧@svarog这主要是为了开发目的,主要是在生产服务器上,您不会遇到此问题。如果是浏览器抛出,并且在后端,Http方法选项被阻止,是否会产生任何效果,就像浏览器不会为POST/PUT as选项调用相应的API失败一样?它可以工作,但在OWASP中,建议不要公开选项。您可以在后端/托管服务(Nginx、Apache)等中阻止它。
express.use('*',(req,res,next) =>{
      if (req.method == "OPTIONS") {
        res.status(200);
        res.send();
      }else{
        next();
      }
    });