访问控制允许Origin标头仅在Chrome,Safari中出错,​​但不在Opera

时间:2016-09-16 13:15:57

标签: javascript angularjs caching

我在我的apache网络服务器上启用了Access-Control-Allow-Origin。我可以在第一次加载时加载所有请求。但是,随后加载/刷新页面会使一半的请求失败,并留下错误

XMLHttpRequest cannot load http://***. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

在Chrome开发者工具的“网络”标签下,启用"禁用缓存"删除此错误。

我使用AngularJS $ http来调用我的请求,我已将缓存选项更改为true / false但这种异常仍然存在。为了您的信息,我也使用角度缓存模块,https://github.com/jmdobry/angular-cache,我也试过启用/禁用它,但无济于事。

以下是请求标头的副本:

GET ***Valid_Url_With_Parameters** HTTP/1.1
Host: ********
Connection: keep-alive
Accept: application/json, text/plain, */*
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

我有两种不同类型的响应标头,其中包含针对失败请求的不同HTTP状态代码。

HTTP/1.1 200 OK
Content-Length: 564121
Content-Type: application/json
Server: Apache/2.2.15 (CentOS)
Vary: Accept
Last-Modified: Fri, 16 Sep 2016 12:41:41 GMT
Connection: keep-alive
Date: Fri, 16 Sep 2016 12:43:44 GMT


HTTP/1.1 206 Partial Content
Content-Type: application/json
Server: Apache/2.2.15 (CentOS)
Vary: Accept
Last-Modified: Fri, 16 Sep 2016 13:39:05 GMT
Content-Range: bytes 29200-29200/785592
Content-Length: 1
Connection: keep-alive
Date: Fri, 16 Sep 2016 14:20:48 GMT

这似乎与缓存有关。页面第一次加载时,所有请求都具有正确的访问控制标头。后续刷新/重新加载会删除此标头。如何继续使用缓存并保留访问控制标题?

编辑:

只是为了补充一下,我尝试使用Safari,出现了同样的异常。它在第一次尝试时加载,但后续加载将抛出无访问控制允许原始错误。但是,这次,Safari中的响应标题显示为空白。

编辑2:

Firefox中也出现异常,但Opera Beta版本40.0.2308.52中没有。我开始怀疑这是否是浏览器的原因。 Access-Control-Allow-Origin标头也存在。

Opera中的响应标头

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Date: Sat, 17 Sep 2016 06:56:53 GMT
Server: Apache/2.2.15 (CentOS)
Vary: Accept
Transfer-Encoding: chunked

编辑3: 我想补充一点,我所提取的请求是大量数据。我拉了最近7天的数据历史,大约有20个JSON文件,每个文件的范围从500KB到1000KB。我注意到,当我更改查询参数以引入较小的数据历史时,不会发生此错误。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:0)

我发现的一项工作是在服务器上动态生成javascript文件,作为页面中包含的资源。这并不需要AJAX,它被CORS阻止并且可以被缓存。

答案 1 :(得分:0)

我建议您在浏览器中添加chrome扩展名

  

Allow-Control-Allow-Origin:*

答案 2 :(得分:0)

在“Access-Control-Allow-Origin”标头中返回特定值时,我们在 Chrome 中遇到了同样的问题。我们还通过在响应标头中包含 Vary: Origin 来解决该问题。

Chrome 似乎将响应标头(包括“Access-Control-Allow-Origin”)视为缓存响应的一部分。因此,如果它从不同的来源请求相同的文件,则缓存中的标头将不匹配。但是,如果您包含 Vary: Origin,它会让 Chrome 知道响应(在我们的例子中只有这个标头)会根据请求的来源而有所不同。

page on MDN解释了:

<块引用>

如果服务器发送带有 Access-Control-Allow-Origin 的响应 明确来源的值(而不是“*”通配符),然后 响应还应该包含一个带有值的 Vary 响应头 Origin — 向浏览器表明服务器响应可能不同 基于 Origin 请求标头的值。