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

我开发了一个 PhoneGap 应用程序,现在正在转换成一个移动网站。除了一个小故障之外,一切都很顺利。我通过 POST 请求使用某个第三方 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)发送 OPTION 请求,并直接跳到实际的 POST 请求?我正在使用 AngularJS1.2.0。

先谢谢你。

159309 次浏览

The preflight is being triggered by your Content-Type of application/json. The simplest way to prevent this is to set the Content-Type to be text/plain in your case. application/x-www-form-urlencoded & multipart/form-data Content-Types are also acceptable, but you'll of course need to format your request payload appropriately.

If you are still seeing a preflight after making this change, then Angular may be adding an X-header to the request as well.

Or you might have headers (Authorization, Cache-Control...) that will trigger it, see:

As what Ray said, you can stop it by modifying content-header like -

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

For Example -

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'}
});
}]);

Or directly to a call -

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


$http(req).then(function(){...}, function(){...});

This will not send any pre-flight option request.

NOTE: Request should not have any custom header parameter, If request header contains any custom header then browser will make pre-flight request, you cant avoid it.

When performing certain types of cross-domain AJAX requests, modern browsers that support CORS will insert an extra "preflight" request to determine whether they have permission to perform the action. From example query:

$http.get( ‘https://example.com/api/v1/users/’ +userId,
{params:{
apiKey:’34d1e55e4b02e56a67b0b66’
}
}
);

As a result of this fragment we can see that the address was sent two requests (OPTIONS and GET). The response from the server includes headers confirming the permissibility the query GET. If your server is not configured to process an OPTIONS request properly, client requests will fail. For example:

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

setting the content-type to undefined would make javascript pass the header data As it is , and over writing the default angular $httpProvider header configurations. Angular $http Documentation

$http({url:url,method:"POST", headers:{'Content-Type':undefined}).then(success,failure);

I think best way is check if request is of type "OPTIONS" return 200 from middle ware. It worked for me.

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

Preflight is a web security feature implemented by the browser. For Chrome you can disable all web security by adding the --disable-web-security flag.

For example: "C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="C:\newChromeSettingsWithoutSecurity" . You can first create a new shortcut of chrome, go to its properties and change the target as above. This should help!