我正在尝试以分块模式发送数据。所有标头均已正确设置,数据也已相应编码。浏览器将我的响应识别为分块响应,接受标头并开始接收数据。
我期待浏览器会在每个收到的块上更新页面,而不是等到所有块都收到然后显示它们。这是预期的行为吗?
我期待看到每个块在收到后立即显示。使用时curl
,每个块在收到后立即显示。为什么 GUI 浏览器不会发生同样的情况?他们是否使用某种缓冲/缓存?
我将Cache-Control
标头设置为no-cache
,所以不确定它与缓存有关。
我正在尝试以分块模式发送数据。所有标头均已正确设置,数据也已相应编码。浏览器将我的响应识别为分块响应,接受标头并开始接收数据。
我期待浏览器会在每个收到的块上更新页面,而不是等到所有块都收到然后显示它们。这是预期的行为吗?
我期待看到每个块在收到后立即显示。使用时curl
,每个块在收到后立即显示。为什么 GUI 浏览器不会发生同样的情况?他们是否使用某种缓冲/缓存?
我将Cache-Control
标头设置为no-cache
,所以不确定它与缓存有关。
afaik 浏览器需要一些有效负载来在收到时开始渲染块。
Curl当然是个例外。
尝试在您的第一个块之前发送大约 1KB 的任意数据。
如果你做的一切都是正确的,浏览器应该在收到块时渲染它们。
修复你的标题。
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 规定,如果没有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 文本是发送者的意图。在没有 MIME-Version 或存在语法上无效的 Content-Type 标头字段的情况下,仍可以假定纯 US-ASCII 文本,但发件人的意图可能不是这样。
浏览器将开始缓冲text/plain
一定量,以检查它们是否可以检测发送的内容是否真的是纯文本或某种媒体类型(如图像),以防Content-Type
被省略,这将等于text/plain
内容类型。这称为 MIME 类型嗅探。
MIME 类型嗅探由 Mozilla 定义为:
在没有 MIME 类型的情况下,或者在某些浏览器认为它们不正确的情况下,浏览器可能会执行 MIME 嗅探——通过查看资源的字节来猜测正确的 MIME 类型。
每个浏览器在不同情况下执行 MIME 嗅探的方式不同。(例如,如果发送的 MIME 类型不合适,Safari 将查看 URL 中的文件扩展名。)由于某些 MIME 类型代表可执行内容,因此存在安全问题。服务器可以通过发送 X-Content-Type-Options 标头来防止 MIME 嗅探。
根据Mozilla 的文档:
X-Content-Type-Options
响应 HTTP 标头是服务器用来指示Content-Type
标头中通告的 MIME 类型不应更改和遵循的标记。这 允许选择退出 MIME 类型嗅探,或者换句话说,这是一种表示网站管理员知道他们在做什么的方式。
因此,添加X-Content-Type-Options: nosniff
使其工作。
无论数据是否分块发送,浏览器都可以处理和呈现数据。浏览器是否呈现响应数据将取决于数据结构以及它采用何种缓冲。例如,在浏览器可以渲染图像之前,它需要有文档(或足够的文档)、样式表等。
当资源响应生成时资源的长度未知(响应标头中不能包含“Content-Length”)并且服务器不想在资源被转移。