【问题标题】:Backbone model CORS fetch not being sent未发送主干模型 CORS 获取
【发布时间】:2014-06-25 04:22:31
【问题描述】:

我正在尝试使用来自另一个域的 model.fetch(),但我似乎偶然发现了一堵墙。似乎我可以进行跨域请求或设置自定义标头(哪个都没有关系),而不是两者兼而有之。不幸的是,我需要两者,因为我试图从中获取的 API 使用基本身份验证。

简而言之:

var Model = Backbone.Model.extend({
    url: function() {
        return a_cross_domain_url;
    },
    initialize: function() {
        this.fetch();
    }
});

Backbone.sync = _.wrap(Backbone.sync, function(sync, method, model, options) {
    if (!options.xhrFields) {
        options.xhrFields = {withCredentials:true};
    }

    options.headers = options.headers || {};

    // credentials is a string that looks like 'Basic d2Vwb3c6McriNzk3YZgvZTNkMTkzOGE4MTk3NjMwMDkzNmMwZGI='
    options.headers['Authorization'] = credentials;

    sync(method, model, options);
});

var m = new Model();

我抽象了很多代码,但我认为这是相关信息。重要的是最终请求看起来像这样:

据我了解,这就是我所需要的一切。这很有趣,因为 $.ajax.beforeSend 函数确实被触发了,但是根本没有实际 GET 触发的日志(服务器什么也没收到)。它似乎在它被调用之前就被取消了。错误回调确实触发,并打印:

SyntaxError: JSON.parse: unexpected end of data

JSON.parse 可能是因为当错误到达时我希望服务器提供 JSON 以在我的应用程序上将它们显示给最终用户,但是,除了该消息之外,我没有得到任何关于正在发生的事情的线索或取消请求的原因。

最后一点,如果我从请求中删除标头(在上面的 js 上),GET 将被执行,但由于没有身份验证而被服务器拒绝。

任何关于发生了什么的想法将不胜感激。

【问题讨论】:

  • 我对 CORS 不是很熟悉,但我认为您发出请求的域中的服务器必须发送此标头:Access-Control-Allow-Origin: *。然后它会发出一个预检请求 (OPTIONS) 以检查其他服务器是否允许 CORS 或类似的东西……看看这里html5rocks.com/en/tutorials/cors 我的意思是它可能与你的代码无关但服务器设置做 CORS 请求。
  • @j03w 你可能是对的。我将与 API 维护人员交谈并保持此线程更新。我以为这已经完成了,因为其他一些人使用 API 没问题,但刚刚被告知他们都在使用移动设备来访问它,所以它可能与我在 web 中需要的不同。谢谢!

标签: jquery ajax backbone.js cors


【解决方案1】:

所以,这是一段坎坷的旅程,但我最近学到了很多关于 CORS 之类的知识,我想我不妨回答这个问题,让子孙后代意识到。希望这会对那里的人有所帮助。

首先,一点背景:

这是一个简单的表单,它被发送到另一个域上的服务器,因此是 CORS 位。我正在使用 Backbone 来处理客户端、服务器上的 Rails 和 HAL 来管理周围的数据。 CORS 使用 Basic Auth 处理。收到数据后,服务器会响应 201 - Created、一个空的正文和一个我接下来应该去的位置响应标头。

这带来了很多啊哈的时刻,我将与你分享。

基本认证

@j03w 当他提到这可能不是前端故障,而是后端时,他是当场的。确实,导致我的请求失败的原因是预检请求中缺少标头。事实证明,如果此预检失败,则不会显示任何请求,即使在技术上发生了一个请求。通过this nifty gem 很快解决了这个问题。

但这还没有结束。

空响应?你要受苦了!

我现在可以与服务器交互,但是当表单发布时,响应是“201 - Created”代码,这是一个成功代码,但没有调用成功回调。取而代之的是,错误接管了。为什么?好吧,事实证明我的服务器在响应正文中没有返回任何内容。这是有错的人。

起初,我认为这是 Backbone 的错,因为它期望更新的模型作为响应。事实证明,这不是 Backbone 的错。它仍然期待来自服务器的更新模型,但这不是触发错误回调的原因。这实际上是 jQuery 的错。 As of 1.9, an empty string returned for JSON data is considered to be malformed JSON (because it is)

但是服务器不想返回模型! (我是一名前端开发人员,但我假设后端人员有一个非常好的理由不这样做)。我该如何解决这个问题?

好吧,事实证明更改状态代码解决了这个问题。代替“201 - Created”,使用“204 - No Content”。 jQuery 完美地处理了这个问题,现在调用了成功回调。

搬家的问题

这个痛苦的比需要更长的旅程的最后一步是将用户重新定位到服务器在 Location 响应标头中发送的 url。 “非常简单!” - 天真的开发者说。 “我只需要使用 xhr.getResponseHeader('Location') 访问标题!” ——他兴奋地叫道。

除非那不起作用。经过一些调试(在简单的 console.log(xhr.getAllResponseHeaders() 之前尝试了所有内容)之后,我发现它没有返回 Location 标头。实际上,它只返回了 2 个无用的标头:Cache-Control 和 Content-类型!我不需要这个!我把头转向我的萤火虫控制台上的 POST 请求的响应,它就在那里。位置标头正在发送,以及 xhr.getAllResponseHeaders() 的许多响应标头没有返回!为什么,以 triforce 的名义,这不起作用?

好吧,事实证明它还需要更多配置。更多的服务器配置选项证明我们需要使用“Access-Control-Expose-Headers”明确告知客户端可以读取哪些标头。在那里列出“位置”解决了这个问题。

resource '*', { 
  headers: :any,
  expose:  ['Location'],
  methods: [:get, :post, :options]
}

所以你有它。这是一段漫长而坎坷的旅程,但我希望这能帮助人们在处理所有这些技术时更快地解决问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-14
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    • 2012-03-29
    相关资源
    最近更新 更多