如何使用 HTTP/1.1 响应禁用 Apache 中的 Transfer-Encoding: Chunked

如何使用 HTTP/1.1 响应禁用 Apache 中的 Transfer-Encoding: Chunked

我有一个 mod_include(SSI)页面,当 HTTP/1.1 浏览器请求时,该页面在分块编码期间会生成错误输出。

当通过 HTTP/1.0 请求时,页面输出正常(因为输出未分块)。

我该如何告诉 Apache不是当HTTP / 1.1浏览器请求时使用分块编码?

更多信息:错误的分块输出是由于在带有 sparc 处理器的 Solaris 5.10 机器上启用了 sendfile() 支持而导致的。禁用 sendfile() 支持可使此问题消失;但是我正在尝试捕获此错误并修复它。

答案1

如果预先指定了 Content-length,Apache 就不必使用 Chunked。如果没有 Content-length,Apache 就别无选择,只能使用它。

要清楚:HTTP/1.0 可以管理它,因为 Apache 在发送之前会读取整个响应,因此它知道响应有多大。这非常低效,而且很慢,据我所知,没有办法为 HTTP/1.1 请求启用此逻辑,除非将它们强制为 HTTP/1.0(您真的不想这样做,对吧?如果您这样做,要设置的环境变量是“降级-1.0”

答案2

上述答案不正确。

如果请求是 HTTP/1.0,Apache 在发送响应之前绝不会缓冲响应(使用 Content-Length 标头)。当然 Apache 可以这样做,但 Apache 使用了更优雅的解决方案:它使用“Connection: close”标头进行响应,并在发送所有数据后立即关闭连接。

根据HTTP 规范,存在“Connection:close”标头意味着客户端需要读取直到连接关闭。

解决您的问题的方法是通过设置上述内容强制 Apache 将请求视为 HTTP/1.0降级-1.0环境变量。分块传输编码 (Chunked Transfer-Encoding) 是 HTTP/1.1 功能,Apache 不会将其用于 HTTP/1.0 请求。

例如,下面是如何禁用 php 文件的分块响应的方法:

++++++++++++
apache.conf
++++++++++++

<Files *.php>
    SetEnv downgrade-1.0
</Files>

答案3

Apache 客户端将尝试确定所发送正文的大小。除非使用特殊拦截器,否则预先指定“Content-Length”将导致错误。

它会检查要发送的实体,以确定它是否已分块或主体的大小 (content-length) 是否 < 0,如果任一情况为真,则使用“Transfer-Encoding=chunked”标头。如果实体不喜欢分块,并且发现内容长度 > -1,则使用“Content-Length”标头。

通常,如果主体的来源是 MIME 主体部分,它将使用“Transfer-Encoding”,因为对 size() 方法的调用返回 -1,因此将 MIME 主体部分转换为字节数组将起作用,因为它将返回数组中的字节数。

答案4

我通常会先进行研究,但由于答案不一且没有任何效果,我决定开始尝试。几个小时后,我想出了设置这两个标题的方法:

Content-Length: 0
Content-Type: application/octet-stream

如果这样做,Apache 根本不会添加Transfer-Encoding标头。我添加了正在传输的 TCP 有效负载数据和标头的屏幕截图,以证明将长度设置为零不会影响返回。请注意,可能对未来的自己来说,我正在使用 WebSocket 编码的消息(二进制内容)通过 HTTP 升级直接发送回,使用 Apache 的默认分辨率(当前为 index.php)。Wireshark 最终将以可读文本显示这些消息。具体来说,数据帧是编码处理的内容,它们不会混淆文本。从 WebSocket 的角度来看,只有当所有三个自定义掩码都设置为零时,这才是正确的。?通常不设置掩码位。

使用 Apache 版本 2.4.58 发送的标头 数据已转移证明

相关内容