NodeJS-如何在没有缓冲的情况下流式传输请求体



在下面的代码中,我不明白req.pipe(res)为什么不起作用,但也没有抛出错误。直觉告诉我这是因为nodejs的异步行为,但这是一个非常简单的情况,没有回调。

我错过了什么?

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);

这是卷曲:

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

以下是调试输出(见正文已上传):

  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"
}

最后的卷曲调试是

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

此外,当我用大的请求体进行压力测试时,我会得到一个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);

将req管道传输到res.req是可读流,response是可写流.它应该能在中工作

   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关闭了,发布数据的文件名前面应该加一个@,如图所示。否则你只会发布文件名。

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

由于IO在节点中是异步的,当您发出.pipe命令时,控制将立即返回到当前上下文,而管道在后台工作。当您下一次调用res.end()时,您将关闭流,防止写入更多数据。

这里的解决方案是让.pipe结束流本身,这是默认的。

我可以想象,时间之所以发挥作用,是因为在不同的机器和不同的数据大小上,异步IO理论上可以在可写流上的结束事件完全处理之前完成(小数据集的快速IO)。

我推荐这篇博客文章,以获得更多的上下文。

相关内容

  • 没有找到相关文章

最新更新