10

在下面的代码中,我无法弄清楚为什么 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"
}

...最终的 curl 调试是

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

?

4

2 回答 2

8

管道 req 到 res。Req 是可读流,响应是可写流。它应该可以工作

   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);
于 2013-07-31T03:48:03.763 回答
6

因此,首先,您的 curl 似乎已关闭,已发布数据的文件名应以 @ 开头,如此处所示。否则,您只会发布文件名。

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

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

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

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

我会推荐这篇博文以获得更多背景信息。

于 2013-08-06T18:31:17.250 回答