分块传输编码 - 浏览器行为
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 Content-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)