向Backbone.js添加HTTP基本身份验证标头同步功能可防止在Save()上更新模型

时间:2013-02-07 13:30:45

标签: javascript backbone.js http-headers cherrypy http-basic-authentication

我正在开发一个由使用Python的CherryPy框架编写的restful API驱动的Web应用程序。我开始用jQuery和服务器端模板的组合编写用户界面,但最终切换到Backbone.js,因为jQuery失控。

不幸的是,我在让我的模型与服务器同步时遇到了一些问题。以下是我的代码中的一个简单示例:

$(function() {
    var User = Backbone.Model.extend({
        defaults: {
            id: null,
            username: null,
            token: null,
            token_expires: null,
            created: null
        },

        url: function() {
            return '/api/users';
        },

        parse: function(response, options) {
            console.log(response.id);
            console.log(response.username);
            console.log(response.token);
            console.log(response.created);
            return response;
        }
    });

    var u = new User();
    u.save({'username':'asdf', 'token':'asdf'}, {
        wait: true,
        success: function(model, response) {
            console.log(model.get('id'));
            console.log(model.get('username'));
            console.log(model.get('token'));
            console.log(model.get('created'));
        }
    });
});

正如您可能知道的,这里的想法是使用该服务注册新用户。当我调用u.save();时,Backbone确实向服务器发送了POST请求。以下是相关内容:

请求:

Request URL: http://localhost:8080/api/users
Request Method: POST
Request Body: {"username":"asdf","token":"asdf","id":null,"token_expires":null,"created":null}

响应:

Status Code: HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 109
Response Body: {"username": "asdf", "created": "2013-02-07T13:11:09.811507", "token": null, "id": 14, "token_expires": null}

如您所见,服务器成功处理了请求,并发送了idcreated的值。但由于某些原因,当我的代码调用console.log(u.id);时,我得到null,当我的代码调用console.log(u.created);时,我得到undefined

tl; dr :为什么Backbone.js在调用save()后不会对我的对象进行持续更改?

修改 我修改了上面的代码,以便使用success回调中的get函数访问模型属性。这应解决原始代码的任何并发问题。

我还在模型的parse函数中添加了一些控制台日志记录。奇怪的是,每个都是undefined ...这是否意味着Backbone.js无法解析我的响应JSON?

编辑2: 几天前,我发现该问题实际上是一个自定义标头,我添加到每个启用HTTP基本身份验证的请求。有关详细信息,请参阅this answer

4 个答案:

答案 0 :(得分:3)

此代码:

u.save();
console.log(u.id);
console.log(u.username);
console.log(u.token);
console.log(u.created);

立即运行......之后没有任何内容可以运行,排队的ajax请求开始了。然后响应稍晚,只有在那一点上改变了值。

似乎这些属性不是直接在对象上,但是保存的异步处理仍然存在,即使您将该代码更正为console.log(u.get("id"))等,也无法获得预期的结果。 / p>

答案 1 :(得分:3)

我想出了这个问题,虽然我仍然无法解释为什么这是一个问题。我正在构建的Web应用程序具有身份验证过程,该过程需要与所有请求一起传递HTTP基本身份验证标头。

为了使用Backbone工作,我覆盖了Backbone.sync函数并更改了line 1398以添加标题。

原始代码:

var params = {type: type, dataType: 'json'};

修改后的代码:

var params = {
    type: type,
    dataType: 'json',
    headers: {
        'Authorization': getAuthHash()
    }
};

函数getAuthHash()只返回表示相应身份验证信息的Base64字符串。

由于某种原因,添加此标头会导致同步/保存功能失败。如果我把它拿出来,一切都按照你的预期运作。

赏金仍然是开放的,我很乐意将奖励给任何可以解释原因的人,并为问题提供解决方案。

修改

看起来问题是我在请求中添加标头的方式。有一个很好的小JavaScript库available on Github通过正确添加HTTP Basic Auth标头来解决这个问题。

答案 2 :(得分:2)

我已经测试了你的代码,它对我来说很好。

在此处查看演示,jsfiddle.net/yxkUD/

答案 3 :(得分:1)

尝试将自定义的beforeSend方法添加到ajax请求以添加自定义标头。

例如: https://github.com/documentcloud/backbone/blob/master/backbone.js#L1424