Nginx删除分块内容的内容长度头

我使用nginx 1.2.3来代理脚本:

proxy_set_header Host $host; proxy_pass http://127.0.0.1:8880; proxy_buffering off; proxy_read_timeout 300s; gzip off; 

脚本发送传输编码:分块和内容长度:251:

 HTTP/1.0 307 Temporary Redirect Content-length: 251 Pragma: no-cache Location: /... Cache-control: no-cache Transfer-encoding: chunked 

我需要两个,但nginx自动删除内容长度:

 HTTP/1.1 302 Found Server: nginx/1.2.3 Content-Type: application/json; charset=utf-8 Content-Length: 58 Connection: keep-alive Location: /... 

结果,客户端不会等待发送数据块。 这曾经用于早期版本的nginx。

不幸的是,我不能评论cnst的post – 所以我会在这里回答。

默认情况下, nginx_http_proxy模块与HTTP / 1.0中的上游进行通信。 这可以通过指令proxy_http_version 1.1进行修改。

这也可能是脚本返回HTTP / 1.0答案的原因,尽pipe此版本中不包含分块编码和状态码307

你不应该使用redirect编码,因为这没有什么意义。

此外 ,似乎nginx 并没有将上游的数据逐个传递给客户端,而是缓冲了上游的响应Content-Length标题字段被忽略,因为它违背了定义。 我不得不看看模块的源代码 ,因为所有这些似乎都是无证的。

您可能需要尝试nginx_tcp_proxy_module将分块的内容作为原始TCP数据进行代理: Github上的模块


UPDATE (10.04.14)
nginx_http_proxy模块支持X-Accel-* ,其中一个( X-Accel-Buffering: yes|no )控制是否caching响应。

将这个头( X-Accel-Buffering: no )添加到后端的响应将导致nginx直接将块传递给客户端。

这个头允许在每个请求的基础上控制缓冲。

该模块还有一个configuration指令 proxy_buffering来启用或禁用响应缓冲(不缓冲意味着发送块将工作)。

代理缓冲(基于头和指令) 在这里被logging。

正如Lukas所指出的那样,如果有一个Transfer-Encoding集,HTTP 1.1将禁止Content-Length

引用http://www.ietf.org/rfc/rfc2616.txt

  3.If a Content-Length header field (section 14.13) is present, its decimal value in OCTETs represents both the entity-length and the transfer-length. The Content-Length header field MUST NOT be sent if these two lengths are different (ie, if a Transfer-Encoding header field is present). If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored. 

您还没有具体阐述为什么您的脚本首先需要分块编码,尤其是redirect响应。

我在这里看到很多问题。

  • Transfer-Encoding: chunked是一个HTTP/1.1function(你的脚本似乎是用HTTP/1.0头来回复)

  • HTTP/1.0没有307

  • chunked的全部目的是你不知道你的Content-Length会是什么,所以chunked用来代替在Content-Length内提供Content-Length ,而在响应的主体内部提供长度,混合与实际内容; 脚本生成两个标头是没有意义的

我个人不熟悉chunked ,但根据http://en.wikipedia.org/wiki/Chunked_transfer_encoding和http://tools.ietf.org/html/rfc2616#section-3.6.1的基本信息,我会猜测你的脚本对分块编码的整个处理可能是完全错误的。

如果上述内容仍然没有涉及到,并且在所有的情况下,也不清楚为什么应该给“ 307或“ 302 http状态码的回复提供一个“奇怪的”编码。 最近在nginx邮件列表中有类似的讨论,大概有410 Gone和其他的错误页面总是排除在gzip压缩之外,我认为这里的情绪同样适用。 ( http://mailman.nginx.org/pipermail/nginx/2013-March/037890.html

我有相同的问题通过HTML5video标签streammp4文件。

Safari和Firefox运行正常,而Chrome在某些时候触发了ERR_CONTENT_LENGTH_MISMATCH(但它允许我在发生故障前扫描video的几分钟)。

在closures对mp4文件的caching控制后,问题没有再现。