使用Node.JS提供HTTP/1.0响应(未知内容长度,分块传输编码)

14

问题

我正在通过Node.JS提供一个长度未知的资源。由于这个原因,无法设置Content-Length头信息。在HTTP 1.1中,此类资源需要使用分块编码(chunked encoding)传输。Node.JS知道这一点,并自动使用分块传输编码来发送数据,附带以下头信息:

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Connection: close
...

这对于表现良好的客户端来说都没问题。 然而,我需要支持一些行为不佳的客户端(即Android 2.2及更早版本)。 这些客户端无法正确支持分块传输编码。

修复尝试 #1

我的第一个想法是将编码设置为none,如下所示:

response.writeHead(200, {'Transfer-Encoding': 'none'});

这将禁用 Node.JS 的自动分块编码并保持与大多数客户端的兼容性。然而,现在我遇到了问题,Android 2.3+客户端无法处理这种错误的传输编码标头,只会咳嗽和窒息。

尝试修复 #2(需要帮助的地方)

当我使用HTTP/1.0进行请求时,服务器正确返回未分块编码的响应:

HTTP/1.1 200 OK
Connection: close
...

这解决了我的问题,并使我能够为所有麻烦的客户端提供有效的流。我不必发送一个虚伪的转移编码(Transfer-Encoding)头,并且仍然不必指定内容的长度。

如何强制Node.JS的HTTP服务器始终以HTTP/1.0模式提供服务?

3个回答

8

针对我的需求,我找到了一种简单的方法来禁用强制使用chunked的方法,就是利用响应对象的一个未记录的属性:

response.useChunkedEncodingByDefault = false;

就是这么简单。当然,依赖于这个属性在未来版本的Node.js中可用并不是最好的选择。也许有更好的解决方案,但目前对我来说这个方法是有效的。


@JamundFerguson,我没有看到过。这个解决方案对你不起作用吗? - Brad
所以,当代码通过CDN传递到NGINX再到我们的节点服务器时,我们会遇到这个问题。在这些情况下,我们在移动浏览器中看到“无法解码原始数据”的错误。通过执行curl -H "TE: chunked;q=1.0" -k --compressed http://nginx/可以(对我们来说)部分地重现该问题,但无论如何。我们的NGINX版本较旧,更新它似乎可以解决我们的问题。 - Jamund Ferguson
@JamundFerguson,嗯,可能在某个地方头部被搞砸了。另外,您的响应头中是否设置了 Vary: Transfer-Encoding, Accept?(对于不可缓存的资源并不重要。)我建议您发布一个新问题,并发送给我一个链接。 - Brad
以下是阻止在Node.js中进行良好修复的代码行:https://github.com/joyent/node/blob/master/lib/_http_server.js#L221 HTTP状态行被硬编码为HTTP/1.1。唯一的解决方法是直接与套接字进行交互。 - Brad

2

强制非分块响应的正确方法

有一种支持的方式可以关闭分块编码:您只需使用request.removeHeader(name)删除Transfer-Encoding头即可:

response.removeHeader('transfer-encoding');

无论什么情况,Node.js都会尊重它。甚至有一个测试来防止某人意外更改此行为,因此我认为使用它是相当安全的。

所以你可以坚持尝试#1,但要按照上述描述进行。


太棒了!很高兴看到这个被添加了。我会试一下的,谢谢。 - Brad

1

Transfer-Encoding: identity 也应该起作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接