IE9 重定向缓存、字体和跨域资源共享 (CORS) CDN HTTP 标头

Posted

技术标签:

【中文标题】IE9 重定向缓存、字体和跨域资源共享 (CORS) CDN HTTP 标头【英文标题】:IE9 redirect caching, fonts, and cross domain resource sharing(CORS) CDN HTTP headers 【发布时间】:2013-02-19 04:25:18 【问题描述】:

我以为我有found a solution to the very vexing problem with Firefox and CDN-hosted fonts access,但是IE9来了。

我最近发现了一个非常令人沮丧的 IE9 缓存问题,偶然发现了这个 blog post (IE9 Redirect Caching Nightmare),它让我对实际问题有了更多的了解。

我不得不承认,我不确定上面提到的是否真的是问题,但它似乎已经足够接近了。

问题:

我有一个网站设置有 2 个域(基域和子域)指向同一个服务器,提供完全相同的网站,该网站使用由 Cloudfront 提供服务的 Amazon S3 上托管的 CDN 中的同一组资源。

https://example.com
https://www.example.com

使用@font-face 从我的 CSS 文件加载字体时,我在 IE9 开发人员工具控制台中收到此类错误消息:

CSS3117: @font-face failed cross-origin request. Resource access is restricted.

当我先加载其中一个 URL,然后再访问另一个时,就会发生这种情况。 IE9 Compatibility Mode 中运行。它运行在Document Mode: IE9 Standards

根据我对 CORS 的有限理解以及设置 Access-Control-Allow-Origin HTTP 标头的需要,我已尽职尽责地在 S3 CORS 策略中设置它,并且它在 Firefox 上运行良好。

来自两个域的请求,在请求 CDN 资源时将获得各自的标头。

IE9 似乎尝试对缓存进行一些优化,并缓存了重定向。 这会导致问题,因为 Access-Control-Allow-Origin 标头也被缓存。在不向 CDN 服务器发送请求的情况下,Access-Control-Allow-Origin 标头无法针对不同的域进行更改。

所以我的情况是,请求来自https://www.example.com,而Access-Control-Allow-Originhttps://example.com。这会导致上面的错误消息出现资源受限问题。

再看:我用Firefox 19做了检查,确实出现了上述情况,但是没有遇到IE9那样严格的限制。子域 (https://www.example.com) 请求信息将接受主域 (https://example.com) 的 access-control-allow-origin。 Chrome (Webkit) 似乎并不在意。我不知道哪个浏览器的行为实现是正确的。

根据我在 CDN 中的当前设置,Chrome 和 Firefox 似乎会自动将所有www 子域请求重新路由到主域。只有多次尝试在地址栏中输入www 子域,Chrome 和 Firefox 才会服从。另一方面,IE9 只会转到地址栏中输入的任何地址。 IE9 似乎有点奇怪,但我不确定哪个浏览器的行为实际上是正确的。

从可用性的角度来看,Chrome 和 Firefox 似乎是“正确”的行为。

已知的可能解决方案:

    设置Access-Control-Allow-Origin标头允许所有,即* 在浏览器中关闭缓存 将一个域重定向到另一个域 使用查询字符串区分不同域对资源的调用 将字体作为 data-uri 嵌入到 CSS 中

对于解决方案 1,假设我偏执,只想设置特定域以允许。

对于解决方案 2,如果我为 所有 浏览器设置它不是最佳选择,而且我的网站必须在下载速度通常低于预期的移动设备上运行。

对于解决方案 3,可能,但我仍然对直接处理 IE9 缓存问题的解决方案感到好奇。

对于解决方案 4,实现起来非常困难,尤其是从 @font-face 调用资源时。这是否意味着我必须为不同行的不同域调用动态重新生成 CSS 才能加载字体以绕过问题?似乎违背了 CSS 本身的目的,并为此缓存资源。

编辑:样式表有效,字体加载无效。

对于解决方案5,维护和更新非常繁琐,尤其是在字体文件定期更改的情况下。

问题:在这种特殊情况下,是否有任何已知的方法可以专门处理 IE9 的重定向缓存行为?

非常感谢答案和 cmets。提前致谢!

编辑:更多浏览器测试信息。

【问题讨论】:

【参考方案1】:

解决方案 1: 检查this question。

解决方案 4: 将您的 CSS 文件重命名为 style.php 并使用您需要的任何代码来调用相应的资源。

在页面顶部设置内容类型。

<?php
    header("Content-type: text/css; charset: UTF-8");
?>

More info 来自 Chris Coyier 的 style.php。

【讨论】:

感谢您的回答,另一个问题的链接让我更仔细地研究了这个问题。解决方案 1 已经在 CDN 上实现。看来问题出在 IE9 上,因为它是一个奇怪的问题。我在我的问题中添加了更多信息。解决方案4,我不会使用PHP,但我了解实现的原理。此外,我需要浏览器缓存资源,以便在网站上快速加载页面,尤其是移动客户端。你知道动态生成的样式表是否会被缓存吗?是否绕过标头绕过标头问题? 不,正如问题中所述,我使用亚马逊网络服务。【参考方案2】:

我们在 IE10 和 IE11 中也发现了同样的奇怪行为。

重置浏览器缓存使字体加载没有任何问题。还启用和禁用兼容模式。

但是当切换到另一个子域时,IE 不会渲染字体,因为请求头与响应头不匹配,响应头仍然是最后一个请求的 URL。即使存储桶上的定义是 *.ourdomain.com

,IE 也会始终显示完整的 URL

因此,通过向 S3 存储桶添加 CORS 权限解决了允许对 webfonts 等资产的跨源请求的一般问题 - 这使得 webfonts 在 Firefox 中完美运行。

但我们仍然不知道如何避免 * 并告诉 IE 不要缓存响应头。

【讨论】:

以上是关于IE9 重定向缓存、字体和跨域资源共享 (CORS) CDN HTTP 标头的主要内容,如果未能解决你的问题,请参考以下文章

同源策略和跨域资源共享(CROS)

Google OAuth2:重定向已被 CORS 政策阻止:请求需要预检,不允许遵循跨域重定向

Amazon S3 CORS(跨域资源共享)和 Firefox 跨域字体加载

Ajax跨域:jsonp还是CORS

Web高级 Ajax和跨域CORS

同源策略和跨域解决方案 CORS