分块传输编码 - 浏览器行为

Posted

技术标签:

【中文标题】分块传输编码 - 浏览器行为【英文标题】:Chunked transfer encoding - browser behavior 【发布时间】:2012-11-13 12:28:18 【问题描述】:

我正在尝试以分块模式发送数据。所有标头均已正确设置,数据也已相应编码。浏览器将我的响应识别为分块响应,接受标头并开始接收数据。

我原以为浏览器会在每个收到的块上更新页面,而不是等到所有块都被接收到然后将它们全部显示出来。这是预期的行为吗?

我期待看到每个块在收到后立即显示。使用curl 时,每个块在收到后立即显示。为什么 GUI 浏览器不会发生同样的情况?他们是否使用某种缓冲/缓存?

我将Cache-Control 标头设置为no-cache,所以不确定它与缓存有关。

【问题讨论】:

您在查看哪些浏览器?通常浏览器进行增量渲染,但它们可以在内部缓冲一些东西,因为重新布局很昂贵...... 你在块中发送什么类型的数据?它只是 html 还是您正在发送脚本数据? 我正在发送text/html。在 Firefox 和 Chrome 上试过。两者都在等待接收所有块。 另见(较新的)***.com/q/16909227/179081 【参考方案1】:

afaik 浏览器需要一些有效负载才能在收到时开始渲染块。 Curl 当然是个例外。

尝试在您的第一个块之前发送大约 1KB 的任意数据。

如果你做的一切都正确,浏览器应该在收到块时呈现它们。

【讨论】:

耶!!!就是这样!在 Firefox、Chrome、Safari 甚至 Opera 中完美运行!非常感谢。 1KiB 确实是一个很好的通用值,更多细节请看这里:***.com/q/16909227/1534459 AFAIK 浏览器仅在未收到内容类型标头时才收集上述 1KB 的数据。然后,他们需要数据来对他们要接收的内容做出有根据的猜测。此外,防病毒软件也可能导致此问题,正如我在这里描述的:***.com/a/41760573/1004651【参考方案2】:

无论数据是否分块发送,浏览器都可以处理和呈现数据。浏览器是否呈现响应数据将取决于数据结构以及它采用何种缓冲。例如在浏览器可以渲染图像之前,它需要有文档(或足够的文档)、样式表等。

当资源响应生成时资源的长度未知(响应标头中不能包含“Content-Length”)并且服务器不想关闭资源转移后的连接。

【讨论】:

【参考方案3】:

修复标题。


    截至 2019 年,如果您使用 Content-type: text/html,Chrome 中不会发生缓冲。

    如果您只想流式传输文本,类似于text/plain,那么仅使用Content-type: text/event-stream 也会禁用缓冲。

    如果您使用 Content-type: text/plain,Chrome 仍将缓冲 1 KiB,除非您另外指定 X-Content-Type-Options: nosniff

RFC 2045 specifies,如果没有指定Content-Type,则应假定Content-type: text/plain; charset=us-ascii

5.2。内容类型默认值

采用不带 MIME Con​​tent-Type 标头的默认 RFC 822 消息 通过此协议,将是 US-ASCII 字符集中的纯文本, 可以明确指定为:

Content-type: text/plain; charset=us-ascii

如果没有指定 Content-Type 标头字段,则假定此默认值。 还建议当一个 遇到语法上无效的 Content-Type 标头字段。在 MIME-Version 标头字段的存在和任何不存在 Content-Type 头域,接收用户代理也可以假设 那个纯 US-ASCII 文本是发件人的意图。纯 US-ASCII 在没有 MIME-Version 或 存在语法上无效的 Content-Type 标头字段,但是 发件人的意图可能不是这样。

浏览器将开始缓冲一定量的text/plain,以检查它们是否可以检测到发送的内容是纯文本还是某些媒体类型(如图像),以防Content-Type被省略,这将然后等于 text/plain 内容类型。这称为 MIME 类型嗅探。

MIME 类型嗅探is defined by Mozilla 为:

在没有 MIME 类型的情况下,或者在某些情况下浏览器 相信他们是不正确的,浏览器可能会执行 MIME 嗅探—— 通过查看字节来猜测正确的 MIME 类型 资源。

每个浏览器在不同的环境下执行 MIME 嗅探的方式不同 情况。 (例如,Safari 会查看文件扩展名 发送的 MIME 类型不合适时的 URL。)有安全性 一些 MIME 类型代表可执行内容。服务器可以 通过发送 X-Content-Type-Options 标头来防止 MIME 嗅探。

根据Mozilla's documentation:

X-Content-Type-Options 响应 HTTP 标头是 服务器指示在 Content-Type 标题不应更改和遵循。这 允许选择退出 MIME 类型嗅探,或者换句话说,它是 可以说网站管理员知道他们在做什么。

因此添加X-Content-Type-Options: nosniff 使其工作。

【讨论】:

对我来说,charset=xxxx 是关键。仅使用Content-type: text/plain(在 Firefox 60.0.9esr 中),输出被缓冲,并且仅在接收数据结束时一次性显示。当更改为Content-type: text/plain; charset=us-ascii(或Content-type: text/html; charset=utf8)时,分块渐进式网页渲染突然按预期工作。 @MatijaNalis,应该是 Content-type: text/html; charset=utf-8(或 UTF-8,如果情况重要)

以上是关于分块传输编码 - 浏览器行为的主要内容,如果未能解决你的问题,请参考以下文章

#WEB安全基础 : HTTP协议 | 0x11 HTTP的分块传输模块

分块编码(Transfer-Encoding: chunked)

HTTP中分块编码(Transfer-Encoding: chunked)

是否有任何浏览器支持以分块编码响应发送的预告片?

HTTP协议之chunk编码(分块传输编码)

jQuery 和传输编码分块