什么能解释浏览器间歇性地不加载某些CORS(跨域)JavaScript文件的原因? [英] What could explain the browser intermittently not loading some CORS (crossorigin) javascript files?

查看:163
本文介绍了什么能解释浏览器间歇性地不加载某些CORS(跨域)JavaScript文件的原因?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近将crossorigin属性添加到了某些脚本标签,以使我的脚本能够从其他子域的脚本中收集错误信息.我在nginx中添加了标头,以允许跨域请求.

I recently added the crossorigin attribute to certain script tags to enable my scripts to gather error information from scripts from a different subdomain. I added the header in nginx to allow the cross-origin request.

从那时起,我偶尔会加载页面,而浏览器没有从服务器请求某些javascript文件.重新加载页面可以解决该问题,但是现在已经发生了好几次了.

Since then, I occasionally have a page load without the browser requesting certain javascript files from the server. Reloading the page resolves the issue, but this has happened several times now.

我认为这与CORS有关,但是由于它在大多数时间都有效,所以我不知道如何复制它.

I think this is related to CORS, but since it works most of the time, I have no idea how to reproduce it.

以下是我的代码的摘录:

Here are some excerpts from my code:

Nginx配置包含以下规则,用于特定位置的javascript文件:

Nginx configuration contains this rule for javascript files in a certain location:

add_header 'Access-Control-Allow-Origin' "$http_origin";

我在php页面中的脚本标签:

My script tag in the php page:

<script type="text/javascript" src="<?php print "$host/js/$filename?v=$version";?>" crossorigin></script>

页面加载后,我可以在Firebug中看到script标签是正确的,但是在Firebug的"Net"标签中甚至没有显示请求.通常,即使使用了文件的缓存版本,也会显示一个请求.

When my page loads, I can see in Firebug that the script tag is correct, but in the Firebug Net tab there isn't even a request shown. Normally there is a request shown, even if it uses a cached version of the file.

我在这里发现了一个我认为可能与之相关的问题: 我所有的浏览器都没有发送原始标头 但是,再考虑一下,我认为应该有一个初始请求,该请求将失败并显示在Firebug中.

I found one question here which I thought might be related: all of my browsers are not sending the origin header But thinking about it further, I think there should be an initial request which would fail and which would show in Firebug.

有人对为什么会发生这种现象有任何理论吗?

Does anyone have any theories on why this might be happening?

我为我的CORS请求添加了单独的访问日志. Nginx添加CORS标头的位置中的任何文件也会记录在新的访问日志中.

I added a separate access log for my CORS requests. Any file in the location which gets Nginx adding the CORS header also gets logged in a new access log.

当页面无法加载JavaScript文件时,Nginx正在记录状态为304(未修改)的请求.这意味着Nginx仅在修改后才有条件请求该资源,而Nginx仅将其发送回304.如果缓存的版本未加载CORS标头,则可能无法执行javascript.

When the page fails to load a javascript file, Nginx is logging a request with a 304 status (not modified). That means that Nginx got a conditional request for the resource only if modified, and Nginx sent back the 304 and nothing else. If the cached version was not loaded with the CORS header, then maybe the javascript can not be executed.

我有一个版本号,我将其附加到脚本标签的src上,如上所示.此版本号已更改.那么这是否不应该导致浏览器重新请求所有这些资源,就像它们具有不同的文件名一样?我认为浏览器应该将它们视为未缓存的资源.不应有任何请求可能导致304.这可能是什么原因造成的?

I have a version number which I append to the src of the script tag as shown above. This version number has changed. So shouldn't that cause the browser to re-request all these resources as if they had a different file name? I think the browser should have been treating these as uncached resources. There should not have been any requests that could result in a 304. What could be causing this?

推荐答案

我知道是什么原因造成的.首先,我们需要有关配置的更多信息.

I figured out what's causing this. First, we need more information about the configuration.

我有3个主机,a.my.com,b.my.com和c.my.com.静态文件都是从c.my.com提供的,而html和php是从a.my.com和b.my.com提供的.

I have 3 hosts, a.my.com, b.my.com, and c.my.com. The static files are all served from c.my.com, and the html and php are served from a.my.com and b.my.com.

我将crossorigin属性添加到了脚本标签中,以便可以从脚本中获得有用的错误信息.请在此处查看描述此问题的SO问题:"Cryptic"脚本错误."在Chrome和Firefox中使用Javascript报告

I added the crossorigin attribute to my script tags so I could get useful error information from my scripts. See the SO question describing this issue here: Cryptic "Script Error." reported in Javascript in Chrome and Firefox

我将请求主机用作允许的来源,而不是*,作为将允许的来源列入白名单的先驱.有关更多信息,请参见此问题:如何根据请求中的Origin头正确地将nginx Access-Control-Allow-Origin设置为响应头?

I am using the requesting host as the allowed origin instead of *, as a precursor to whitelisting allowed origins. See this question for more: How to properly setup nginx Access-Control-Allow-Origin into response header based on the Origin header from the request?

我的nginx配置对静态内容有很长的期限,因此可以缓存内容,并且不会因重复的请求而使我的服务器不工作.我将一个版本号附加到静态内容的url上,以便在发生某些更改时可以重新请求它.版本号来自我在svn中的版本,因此,当我将服务器文件更新为最新版本时,浏览器都将开始为每个静态文件加载新的URL.

My nginx configuration has a long expiration for static content so stuff is cached and not loading down my server with repeated requests. I append a version number to the url for static content so it can be re-requested when something changes. The version number comes from my version in svn, so when I update the server files to the newest version, browsers will all start loading a new url for each static file.

这就是发生的事情:

新用户访问a.my.com并加载页面.从c.my.com加载了Java脚本文件1至5,以便在a.my.com上使用. Nginx向它们发送一个带有"a.my.com"的原始标头和一个很远的到期日期.此页面工作正常,并且javascript成功加载.

A new user visits a.my.com and loads the page. Javascript files 1 through 5 are loaded from c.my.com for use on a.my.com. Nginx sends them with an origin header allowing "a.my.com" and a far future expiration date. This page works fine, and the javascript loads successfully.

然后,用户转到b.my.com上站点的另一部分并加载页面.从c.my.com请求Java脚本文件1到10.文件1至5与为a.my.com加载的文件相同.浏览器知道它的缓存中有这些文件,因此它向nginx询问它们的状态. Nginx回复304(未修改),浏览器继续请求下一个文件.

The user then goes on to the other part of the site at b.my.com and loads the page. Javascript files 1 through 10 are requested from c.my.com. Files 1 through 5 are the same files as were loaded for a.my.com. The browser knows it has those files in its cache, so it asks nginx for their status. Nginx replies with a 304 (not modified) and the browser goes on to request the next file.

因此,现在浏览器已从c.my.com加载了文件6至10,并在高速缓存中查找了文件1至5.已缓存的文件附加了它们的allow origin标头,内容为a.my. com"是允许的来源.请求文件的页面位于b.my.com上,因此该页面不匹配,也不允许使用它们.因此,它会静默丢弃它们,并向用户显示缺少javascript的页面.

So now the browser has loaded files 6 through 10 from c.my.com, and has looked in the cache for files 1 through 5. The cached files have their allow origin header attached, and this says "a.my.com" is the allowed origin. The page requesting the files is on b.my.com, so it doesn't match and isn't allowed to use them. So it silently discards them and shows the user a page with missing javascript.

解决方案:

一种解决方案是发送值为*的Access-Control-Allow-Origin,以允许任何来源.这意味着即使原始缓存文件未启动首次下载,也允许该缓存文件为当前原始文件.如下面的SO问题所讨论的那样,这存在安全隐患:何时可以安全启用CORS?

One solution is to send the Access-Control-Allow-Origin with a value of * to allow any origin. This would mean that the cached file is allowed for the current origin even if they didn't initiate the first download. There are security implications for this, as discussed in this SO question: When is it safe to enable CORS?

第二种解决方案是使每个源对同一静态文件使用不同的url.这将迫使浏览器分别缓存它们.这允许Access-Control-Allow-Origin标头特定于单个来源.代价是有更多的资源请求发送到服务器,并且用户的浏览器将更多的内存和存储空间用于缓存的资源.

A second solution is to make each origin use a different url for the same static file. This forces the browser to cache them separately. That allows the Access-Control-Allow-Origin header to be specific to a single origin. The cost is more resource requests coming to the server, and the user's browser uses more memory and storage for cached resources.

这篇关于什么能解释浏览器间歇性地不加载某些CORS(跨域)JavaScript文件的原因?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆