网站搜索

javascript - 跨域 XHR 失败


我有一个托管在某个域上的 API,该 API 启用了 CORS,并具有以下头信息:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Max-Age: 1728000

我能够从 hackst.com 发起 GET 或 POST 请求,并且它运行良好。链接:http://hackst.com/#w3SbV

在我托管于另一个域的 Backbone 应用中,GET 请求工作正常。但当我尝试创建并保存一个新模型(即发起 POST 请求)时,会出现以下错误:

Failed to load resource: the server responded with a status of 501 (Not Implemented) http://projectwhatup.us:5000/api/posts
XMLHttpRequest cannot load http://projectwhatup.us:5000/api/posts. Origin http://ayush.projectwhatup.us is not allowed by Access-Control-Allow-Origin.

我相关的骨干代码:

var newPostData = {
    topic : "New Post",
    body : "new body",          
    user_id : 1,
};  

var newPostModel = new Post(newPostData);
this.model.create(newPostModel);

我甚至尝试过覆盖create方法,并像这样手动发送POST请求:

create : function(data) {
    console.log('overriden create');

    $.ajax({
        "url" : this.url,
        "async" : true,
        "beforeSend" : function(obj){
            console.log(obj);
        },
        "contentType" : 'application/json',
        //"crossDomain" : true,  // uncommenting this doesnt help either
        "headers" : {

        },
        "dataType" : 'json',
        "type" : 'POST',
        "data" : JSON.stringify(data),
        "error" : function(err){
            console.log('new post creation failed');
            console.log(err);
        },
        "success" : function(resp){
            console.log('new post created');
            console.log(resp);
        }
    });
}

相同的错误。

我也在 JSFiddle 上尝试了一个独立的 GET 请求(http://jsfiddle.net/X9cqh/5/),但是即使我的 Backbone 应用可以正常发出 GET 请求,这个请求仍然失败。

我现在完全一头雾水。有任何提示、指点或解决方案吗?

答案#1

服务器还应通过以下头部回应预检请求:

Access-Control-Allow-Headers: Content-Type

这是必要的,因为内容类型是 application/json,而这是超出 CORS 规范(http://www.w3.org/TR/cors/)定义的可接受值的。

答案#2

你的服务器设置有效。显然 JSFiddle 不会发起 ajax 请求,但你可以通过在 Chrome 控制台或 Safari 开发者控制台输入这四行代码来快速测试它是否有效:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://projectwhatup.us:5000/api/posts', false);
xhr.send();
xhr.responseText;

如果你在不允许 CORS 的域上尝试这个,它会出错。