取消掉Transfer-Encoding:chunked

本文深入探讨了Web服务器如何在无法预先确定响应消息大小时使用Chunked编码进行动态传输,解释了Chunked编码的工作原理及具体实现,并提供了PHP版本的解码代码实例。
 
有时候,Web服务器生成HTTP Response是无法在Header就确定消息大小的,这时一般来说服务器将不会提供Content-Length的头信息,而采用Chunked编码动态的提供body内容的长度。

进行Chunked编码传输的HTTP Response会在消息头部设置:

Transfer-Encoding: chunked

表示Content Body将用Chunked编码传输内容。

Chunked编码使用若干个Chunk串连而成,由一个标明长度为0的chunk标示结束。每个Chunk分为头部和正文两部分,头部内容指定下一段正文的字符总数(十六进制的数字)和数量单位(一般不写),正文部分就是指定长度的实际内容,两部分之间用回车换行(CRLF)隔开。在最后一个长度为0的Chunk中的内容是称为footer的内容,是一些附加的Header信息(通常可以直接忽略)。具体的Chunk编码格式如下:

  Chunked-Body = *chunk
         "0" CRLF
         footer
         CRLF 
  chunk = chunk-size [ chunk-ext ] CRLF
       chunk-data CRLF

  hex-no-zero = <HEX excluding "0">

  chunk-size = hex-no-zero *HEX
  chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
  chunk-ext-name = token
  chunk-ext-val = token | quoted-string
  chunk-data = chunk-size(OCTET)

  footer = *entity-header

RFC文档中的Chunked解码过程如下:
  length := 0
  read chunk-size, chunk-ext (if any) and CRLF
  while (chunk-size > 0) {
  read chunk-data and CRLF
  append chunk-data to entity-body
  length := length + chunk-size
  read chunk-size and CRLF
  }
  read entity-header
  while (entity-header not empty) {
  append entity-header to existing header fields
  read entity-header
  }
  Content-Length := length
  Remove "chunked" from Transfer-Encoding

最后提供一段PHP版本的chunked解码代码:

$chunk_size = (integer)hexdec(fgets$socket_fd, 4096 ) );
while(!feof($socket_fd&& $chunk_size > 0) {
    $bodyContent .= fread$socket_fd, $chunk_size );
    fread$socket_fd, 2 ); // skip \r\n
    $chunk_size = (integer)hexdec(fgets$socket_fd, 4096
 ) );
}


要解决服务器不返回Transfer-Encoding:chunked,在客户端请求的时候可以使用http 1.0的协议。

在处理 Nginx 中上游服务器发送重复的 `Transfer-Encoding: chunked` 头部问题时,通常涉及到代理配置或与后端通信方式的调整。当使用 Nginx 作为反向代理时,它会将客户端请求转发到后端服务器,并接收响应再返回给客户端。如果后端服务返回了多个 `Transfer-Encoding: chunked` 头部,Nginx 可能不会自动合并这些头部,从而导致客户端接收到不规范的 HTTP 响应。 解决此类问题的方法包括以下几个方面: 1. **检查后端应用逻辑**:确保后端服务在生成响应时只设置一次 `Transfer-Encoding: chunked` 头部。例如,在 Node.js 的 Express 应用中,可以通过中间件来控制头部输出: ```javascript app.use((req, res, next) => { res.removeHeader('Transfer-Encoding'); // 移除可能已存在的 Transfer-Encoding res.setHeader('Transfer-Encoding', 'chunked'); next(); }); ``` 这种方法适用于能够直接修改后端代码的情况[^1]。 2. **使用 Nginx 配置清理响应头**:通过 Nginx 的 `proxy_hide_header` 指令可以隐藏某些从后端传递过来的头部字段,或者使用 `more_clear_headers`(需要安装 `headers-more-nginx-module`)来清除特定头部,然后再重新添加所需的头部。例如: ```nginx location / { proxy_pass http://backend; more_clear_headers 'Transfer-Encoding'; add_header Transfer-Encoding "chunked"; } ``` 此配置首先清除了所有来自后端的 `Transfer-Encoding` 头部,然后手动添加一个正确的 `Transfer-Encoding: chunked` 头部[^2]。 3. **升级 Nginx 并启用兼容性支持**:某些旧版本的 Nginx 在处理 `Transfer-Encoding` 和 `Content-Length` 同时存在的情况下可能会出现问题。建议升级到最新稳定版 Nginx,并根据需要启用相关的 HTTP 协议优化选项,如 `chunked_transfer_encoding on;`,以增强对分块传输编码的支持[^3]。 4. **调试和日志分析**:启用 Nginx 的访问日志和错误日志,查看具体的请求/响应细节,确认是哪个环节引入了重复的头部。可以通过如下配置开启详细的日志记录: ```nginx http { log_format custom '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" ' '"$upstream_http_transfer_encoding"'; access_log /var/log/nginx/access.log custom; } ``` 日志中的 `$upstream_http_transfer_encoding` 变量可以帮助识别上游服务器是否发送了重复的 `Transfer-Encoding` 头部[^4]。 5. **测试和验证修复效果**:完成上述配置更改后,务必进行充分的测试,确保修复方案有效且没有引入其他副作用。可以使用 `curl -I` 或者 `telnet` 等工具模拟客户端请求,观察响应头部是否符合预期。 通过以上方法,可以有效地解决 Nginx 上游发送重复 `Transfer-Encoding: chunked` 头部的问题。 ---
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值