我开发了一个PhoneGap应用程序,现在正在转换为移动网站。除了一个小故障之外,一切顺利。我通过POST请求使用某个第三方API,这在应用程序中运行良好,但在移动网站版本中失败。
仔细观察后,似乎AngularJS(我猜浏览器实际上)是第一次发送OPTIONS请求。我今天学到了很多关于CORS的知识,但我似乎无法弄清楚如何完全禁用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)发送OPTIONS请求并跳转到实际的POST请求?我正在使用AngularJS 1.2.0。
提前致谢。
答案 0 :(得分:94)
您的内容类型application/json
会触发预检。防止这种情况的最简单方法是将Content-Type设置为text/plain
。 application/x-www-form-urlencoded
& multipart/form-data
内容类型也可以接受,但您当然需要适当地格式化请求有效内容。
如果您在进行此更改后仍然看到预检,那么Angular可能也会在请求中添加X-header。
或者您可能会有触发它的标题(授权,缓存控制...),请参阅:
答案 1 :(得分:13)
正如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(){...});
这不会发送任何飞行前选项请求。
注意:请求不应包含任何自定义标头参数,如果请求标头包含任何自定义标头,则浏览器会进行转机前请求,您无法避免。
答案 2 :(得分:2)
我认为最好的办法是检查请求是否为" OPTIONS"从中间件返回200。它对我有用。
function *combinations(arrOfArr) {
let [head, ...tail] = arrOfArr
let remainder = tail.length ? combinations(tail) : [[]];
for (let r of remainder) for (let h of head) yield [h, ...r];
}
答案 3 :(得分:1)
当执行某些类型的跨域AJAX请求时,支持CORS的现代浏览器将插入额外的"预检"请求确定他们是否有权执行该操作。 来自示例查询:
$http.get( ‘https://example.com/api/v1/users/’ +userId,
{params:{
apiKey:’34d1e55e4b02e56a67b0b66’
}
}
);
作为这个片段的结果,我们可以看到地址被发送了两个请求(OPTIONS和GET)。来自服务器的响应包括确认查询GET的允许性的标头。如果您的服务器未配置为正确处理OPTIONS请求,则客户端请求将失败。例如:
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
答案 4 :(得分:0)
Preflight是由浏览器实现的Web安全功能。对于Chrome,您可以通过添加--disable-web-security标志来禁用所有网络安全。
例如:“ C:\ Program Files \ Google \ Chrome \ Application \ chrome.exe” --disable-web-security --user-data-dir =“ C:\ newChromeSettingsWithoutSecurity”。您可以先创建一个新的chrome快捷方式,转到其属性,然后如上所述更改目标。这应该有所帮助!
答案 5 :(得分:-1)
将content-type设置为undefined将使javascript传递头文件数据原样,并覆盖默认的角度$ httpProvider头配置。 Angular $http Documentation
$http({url:url,method:"POST", headers:{'Content-Type':undefined}).then(success,failure);