哪些限制适用于不透明响应?

Posted

技术标签:

【中文标题】哪些限制适用于不透明响应?【英文标题】:What limitations apply to opaque responses? 【发布时间】:2016-12-30 18:58:52 【问题描述】:

Opaque responses 被定义为Fetch API 的一部分,并表示在未启用CORS 时向远程源发出请求的结果。

关于如何使用不透明响应(来自 javascript 和作为页面上的资源)存在哪些实际限制和“陷阱”?

【问题讨论】:

【参考方案1】:

访问不透明响应的标题/正文

关于不透明响应的最直接限制是,您无法从Response 类的大部分properties 中获取有意义的信息,例如headers,或者调用构成methods 的各种@987654342 @ 接口,如json()text()。这符合不透明响应的黑盒特性。

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

只要浏览器允许使用非 CORS 跨域资源,就可以将不透明响应用作网页上的资源。以下是非 CORS 跨域资源以及因此不透明响应有效的元素子集,改编自 Mozilla Developer Network documentation:

<script> <link rel="stylesheet"> <img><video><audio> <object><embed> <iframe>

不透明响应无效有效的一个值得注意的用例是font resources。

一般来说,要确定是否可以将不透明响应用作页面上的特定类型资源,请查看相关规范。例如,html specification explains 表示非 CORS 跨域(即不透明)响应可用于 <script> 元素,但有一些限制以防止泄漏错误信息。

不透明响应和缓存存储 API

开发人员might run into 响应不透明的一个“陷阱”涉及将它们与Cache Storage API 一起使用。有两条背景信息是相关的:

不透明响应的status 属性为always set to 0,无论原始请求是成功还是失败。 如果任何请求产生的响应具有不在 2XX range 中的状态代码,缓存存储 API 的 add()/addAll() 方法都将拒绝。

从这两点来看,如果作为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,这意味着任何单个缓存的不透明响应对整体存储使用量的最小大小是approximately 7 megabytes。在确定要缓存多少不透明响应时,您应该牢记这一点,因为您很容易超出存储配额限制,比您根据不透明资源的实际大小预期的要快得多。

【讨论】:

它实际上并没有占用设备物理存储空间。这只是对配额计算有贡献的值。 您的答案甚至在此处的 Workbox 指南中被提及:developers.google.com/web/tools/workbox/guides/… 没错,但我确实写了那个 Workbox 指南 :-) 使用图像 CDN 和这种缓存是否是一个糟糕的设计? (浪费分配的空间)是否可以缓存从我们的主域检索到的文件并使用 CDN 链接(密钥)公开它?例如,我可以将网络请求转到cdn.x.com/test.jpg,并将缓存请求转到主域www.x.com/test.jpg 我在这个问题上发现了一个诡计,我不知道这是否是一个不错的解决方案,但我基本上让我的服务人员假装它是 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) 请求缓存,这似乎工作正常。虽然这种方法有什么?

以上是关于哪些限制适用于不透明响应?的主要内容,如果未能解决你的问题,请参考以下文章

Azure API 响应中缺少速率限制标头

CORS 适用于 plnkr,但不适用于浏览器:“响应具有 HTTP 状态代码 403”

UITableView 不响应透明区域的触摸

SDL OpenGL 窗口无响应,透明

RestTemplate + OkHttp3 - gzip'ed响应的透明处理?

如何在响应式方形网格中仅使背景图像透明?