【问题标题】:Adding HTTP Basic Authentication Header to Backbone.js Sync Function Prevents Model from Being Updated on Save()将 HTTP 基本身份验证标头添加到 Backbone.js 同步函数可防止模型在 Save() 时更新
【发布时间】:2013-01-23 00:34:30
【问题描述】:

我正在开发一个 Web 应用程序,该应用程序由使用 Python 的 CherryPy 框架编写的 restful API 提供支持。我开始使用 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}

如您所见,服务器成功处理了请求并返回了id 和created 的值。但是由于某种原因,当我的代码调用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。

【问题讨论】:

  • 您的代码看起来不错(除了您应该使用Model.urlRoot 而不是Model.url,但这不是问题所在)。您的代码的早期版本存在问题,但您确定当前编辑中的确切代码仍然失败吗?

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


【解决方案1】:

这段代码:

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

立即运行...之后没有任何东西可以运行,排队的 ajax 请求开始。然后响应会稍晚一些,并且只有在那个时候值才会改变。

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

【讨论】:

  • 您使用 u.get("id") 而不是 u.id 的建议很有意义,但即使我尝试在成功回调或模型的同步事件中记录这些属性,它们仍然未设置,所以我认为还有更多问题。
  • 我已经编辑了原始问题中的代码以纳入您的建议......它仍然无法正常工作,我无能为力。
  • @MusikPolice 如果您定义了解析函数,那么您有责任从响应中返回解析后的模型。当来自服务器的响应不是直接结构化以创建模型时使用此功能
  • @MusikPolice 你可以像这样在解析函数中调试它console.log( JSON.parse(JSON.stringify(response)))
【解决方案2】:

我发现了这个问题,尽管我仍然无法解释为什么这是一个问题。我正在构建的 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 标头解决了这个问题。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 抱歉,我没有在问题中添加有关该问题的其他详细信息。更多详情请见this description
    【解决方案4】:

    尝试在ajax请求中添加自定义的beforeSend方法来添加自定义的header。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多