整个周末我一直在努力解决这个问题。该问题仅在通过 mac 计算机访问并通过我的 nodejitsu 实例托管时存在,并且在我的本地主机服务器上不存在。
我的申请很典型。它在不同的域上有一个 Web 服务器组件和 REST 服务器——因此需要 CORS。唯一增加的复杂性是自定义标题。
我已经在我的 node.js 服务器上设置了 CORS,如下所示
var allowCrossDomain = function(req, res, next) {
console.log(req.headers);
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Accept, X-api-key, X-auth-token, Content-Type, Content-Length');
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Accept, X-api-key, X-auth-token, Content-Type, Content-Length');
res.send(200, {});
}
else {
next();
}
};
前端 $.ajax 调用是这样的
//create user
$.ajax({
url: host + 'users',
headers: {'X-api-key': apikey},
type: 'POST',
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify({
email: userInfo.email,
username: username,
password: pasword,
}),
xhrFields: {},
crossDomain: true,
success: function (res) {
console.log(res);
$('.messages')
.removeClass('error')
.addClass('success')
.html('<strong>Success! </strong>Check email for activation link');
},
error: function (xhr, status, errorThrown) {
console.log(xhr.responseText);
var errorMessage = $.parseJSON(xhr.responseText);
$('.messages')
.removeClass('success')
.addClass('error')
.html('<strong>Oops!</strong> '+errorMessage.error);
}
});
从技术上讲,这应该可行。这是对节点服务器的教科书 ajax 调用,但是当我在 chrome 中进行调用时,我在 chrome 终端中预检时收到以下错误。
选项 http://api.dev.XXXXX.com/users/login net::ERR_EMPTY_RESPONSE jquery-1.7.2.js:8240 发送 jquery-1.7.2.js:8240 jQuery.extend.ajax jquery-1.7.2.js:7719 (匿名函数)VM62:2 InjectedScript._evaluateOn VM57:730 InjectedScript._evaluateAndWrap VM57:669 InjectedScript.evaluate
在 firefox/mozilla 上是这样,在 Safari 上它非常相似:
“网络错误:502 错误网关 - http://api.dev.XXXX.com/users/fbauth” fbauth 跨域请求被阻止:同源策略不允许在 http://api.dev.XXXX.com/users/fbauth 读取远程资源。这可以通过将资源移动到同一域或启用 CORS 来解决。
我通过在复杂的 HTTP 请求之前向服务器发送简单的 HTTP 请求,以某种方式设法部分绕过了这一点。我不知道为什么这使它起作用,这使它成为世界上最丑陋、最有效的黑客。
$(document).ready(function(){
setTimeout(function(){
$.ajax({
url: host + 'users/login',
type: 'POST',
dataType: 'json',
data: JSON.stringify({
})
});
$.ajax({
url: host + 'users/fbauth',
type: 'POST',
dataType: 'json',
data: JSON.stringify({
})
});
}, 500);
})
现在的问题是,在执行简单的 HTTP 后几乎必须立即执行预检,因此,使用 fb 登录的 oauth 不起作用,因为它在执行需要执行的操作之前对 fb 执行了一些请求并返回。
我完全被困在这里。这是 webkit/mozilla 引擎问题吗?还是我在这里遗漏了一些关键的东西?
这是一个带有对测试端点的示例请求的 jsfiddle。运行时检查控制台。 http://jsfiddle.net/cvnce/6nPLJ/
ISSUE-- 在我的主要开发机器上失败,但它可能对你有用。该请求在我的 6 台计算机中的 4 台上进行了预检和正确验证。