不透明响应有哪些限制?

108

不透明响应Fetch API的一部分定义,代表在未启用CORS时向远程源发出请求的结果。

在JavaScript中以及作为页面资源使用不透明响应时,存在哪些实际限制和“坑点”?

1个回答

157

访问不透明响应的头部/正文

不透明响应最直接的限制是,您无法从Response类的大多数属性中获取有意义的信息,例如headers,或调用组成Body接口的各种方法,例如json()text()。这符合不透明响应的黑盒特性。

将不透明响应作为页面上的资源使用

不透明响应可作为网页上的资源使用,只要浏览器允许使用非CORS跨域资源。以下是一些元素的子集,其中非CORS跨域资源和因此不透明响应是有效的,该子集改编自Mozilla Developer Network documentation
  • <script>
  • <link rel="stylesheet">
  • <img><video><audio>
  • <object><embed>
  • <iframe>
字体资源是一个不适用于不透明响应的显著用例。
一般而言,要确定你是否可以将不透明响应用作页面上特定类型的资源,请检查相关规范。例如,HTML规范解释了非跨源(即不透明)响应可用于<script>元素,但有一些限制以防止泄漏错误信息。
不透明响应和缓存存储API
开发者在使用不透明响应时可能会遇到一个问题,那就是与缓存存储API一起使用时会出现一些问题。需要了解两个相关的背景信息:
  • 不管原始请求成功或失败,不透明响应的 status 属性总是设置为 0
  • 缓存存储 API 的 add()/addAll() 方法都会拒绝任何请求所得到的响应状态码不在 2XX 范围内

由此可知,如果 add()/addAll() 调用中执行的请求结果是不透明响应,则无法将其添加到缓存中。

您可以通过显式执行fetch(),然后使用不透明响应调用put()方法来解决此问题。这样做,您实际上选择了将要缓存的响应可能是由您的服务器返回的错误的风险。
const request = new Request('https://third-party-no-cors.com/', {
  mode: 'no-cors',
});

// Assume `cache` is an open instance of the Cache class.
fetch(request).then(response => cache.put(request, response));

不透明响应和navigator.storage API

为了避免跨域信息泄漏,对于用于计算存储配额限制(即是否抛出QuotaExceeded异常)并由navigator.storage API报告的不透明响应,添加了大量填充。

这种填充的细节因浏览器而异,但对于Google Chrome来说,这意味着任何单个缓存的不透明响应对总体存储使用的最小贡献量约为7兆字节。在确定要缓存多少不透明响应时,您应该记住这一点,因为基于不透明资源的实际大小,您很容易比预期更快地超过存储配额限制。


1
它实际上并没有占用设备物理存储上的那么多空间。它只是对配额计算有贡献的值。 - Jeff Posnick
2
你的答案甚至在Workbox指南中提到了:https://developers.google.com/web/tools/workbox/guides/handle-third-party-requests - Dima Slivin
35
没错,但是我确实写了那个Workbox指南 :-) - Jeff Posnick
2
这种缓存方式与图像CDN结合使用是否是一种不好的设计?(浪费分配的空间)是否可以缓存从我们的主域检索的文件,并使用CDN链接(密钥)公开它?例如,我可以让网络请求转到cdn.x.com/test.jpg,并且缓存请求转到主域www.x.com/test.jpg吗? - cglacet
1
我发现了一个解决这个问题的诡计,但我不知道这是否是一个体面的解决方案,但我基本上让我的服务工作者假装它是CDN。我在缓存中添加域相对URL(例如,/test.jpg),然后对于每个针对cdn.x.com/test.jpg的获取请求,我都使用原始域名修改URL(URL变为www.x.com/test.jpg),我使用类似于这样的代码:const cacheUrl = (url.hostname == 'cdn.x.com')? new URL(event.target.location.origin + url.pathname): url;。然后,我使用这个新的URL caches.match(cacheUrl) 请求缓存,这似乎很好用。对此方法有何想法? - cglacet
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接