NodeJS – 如何stream缓冲请求主体

在下面的代码中,我不知道为什么req.pipe(res)不起作用,但也不会抛出一个错误。 一个预感告诉我,这是由于nodejs的asynchronous行为,但这是一个非常简单的情况下没有callback。

我错过了什么?

http.createServer(function (req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('Echo service: \nUrl: ' + req.url); res.write('\nHeaders:\n' + JSON.stringify(req.headers, true, 2)); res.write('\nBody:\n'); req.pipe(res); // does not work res.end(); }).listen(8000); 

这是curl:

 ➜ ldap-auth-gateway git:(master) ✗ curl -v -X POST --data "test.payload" --header "Cookie: token=12345678" --header "Content-Type:text/plain" localhost:9002 

这是debugging输出(请参阅上传的主体):

  About to connect() to localhost port 9002 (#0) Trying 127.0.0.1... connected Connected to localhost (127.0.0.1) port 9002 (#0) POST / HTTP/1.1 User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8x zlib/1.2.5 Host: localhost:9002 Accept: */* Cookie: token=12345678 Content-Type:text/plain Content-Length: 243360 Expect: 100-continue HTTP/1.1 100 Continue HTTP/1.1 200 OK Content-Type: text/plain Date: Sun, 04 Aug 2013 17:12:39 GMT Connection: keep-alive Transfer-Encoding: chunked 

服务响应而不回应请求主体:

 Echo service: Url: / Headers: { "user-agent": "curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8x zlib/1.2.5", "host": "localhost:9002", "accept": "*/*", "cookie": "token=12345678", "content-type": "text/plain", "content-length": "243360", "expect": "100-continue" } 

…最后的curldebugging是

 Body: Connection #0 to host localhost left intact Closing connection #0 

另外,当我用大请求体testing时,我得到一个EPIPE错误。 我怎样才能避免这一点?

– 编辑:通过反复试验,我得到了这个工作,它仍然指向是一个时间问题。 虽然它仍然很奇怪,因为超时会导致有效负载被返回,但是超时时间并不重要。 换句话说,无论是将超时设置为5秒还是500秒,负载都正确地回送到请求,并且连接终止。

这是编辑:

 http.createServer(function (req, res) { try { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('Echo service: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2)); res.write('\nBody:"\n'); req.pipe(res); } catch(ex) { console.log(ex); // how to change response code to error here? since headers have already been written? } finally { setTimeout((function() { res.end(); }), 500000); } }).listen(TARGET_SERVER.port); 

pipe道需要水库。 要求是可读的stream和响应是一个可写的stream.It应该工作

  http.createServer(function (req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('Echo service: ' + req.url + '\n' + JSON.stringify(req.headers, true, 2)); // pipe request body directly into the response body req.pipe(res); }).listen(9002); 

所以首先,看起来你的curl是closures的,发布数据的文件名应该在前面加@ ,如下所示 。 否则,您只需发布文件名。

除此之外,Chandu是正确的说res.end()的调用是这里的问题。

由于IO在节点中是asynchronous的,因此在发出.pipe命令时,控制立即返回到当前上下文,而pipe道在后台工作。 当你下一次调用res.end() ,你closures了stream, 防止写入更多的数据 。

这里的解决scheme是让.pipe结束stream本身, 这是默认的 。

我想可能是因为在不同的机器和不同的数据大小下,时序才起作用,理论上,asynchronousIO可以在完成处理可写stream上的结束事件之前完成(小数据集的快速IO)。

我会推荐这个博客文章的一些更多的上下文。