【问题标题】:node.js http.request event flow - where did my END event go?node.js http.request 事件流 - 我的 END 事件去哪儿了?
【发布时间】:2011-09-08 04:57:44
【问题描述】:

我正在制定一个巧妙的计划,其中涉及使用 node.js 作为另一个服务前面的代理服务器。

简而言之:

  1. 将传入请求分派到静态文件(如果存在)
  2. 否则,将请求分派给另一个服务

我有基本的工作,但现在试图让整个事情与 Sencha Connect 一起工作,这样我就可以访问所有提供的关键中间件。

所有的动作都发生在dispatchProxy下面

connect(
  connect.logger(), 
  connect.static(__dirname + '/public'),
  (request, response) ->  
    dispatchProxy(request, response)
).listen(8000)

dispatchProxy = (request, response) ->  

  options = {host: host, port: port, method: request.method, headers: request.headers, path: request.url}

  proxyRequest = http.request(options, (proxyResponse) ->
    proxyResponse.on('data', (chunk) ->
     response.write(chunk, 'binary')
    )

    proxyResponse.on('end', (chunk) ->        
     response.end()
    )

    response.writeHead proxyResponse.statusCode, proxyResponse.headers    
  )

  request.on('data', (chunk) ->
    proxyRequest.write(chunk, 'binary')
  )

  # this is never triggered for GETs
  request.on('end', ->
    proxyRequest.end()
  )

  # so I have to have this here
  proxyRequest.end()

您会在上面的最后一行看到 proxyRequest.end()

我发现在处理 GET 请求时,请求的 END 事件永远不会被触发,因此需要调用 proxyRequest.end()。 POST 请求按预期触发 DATA 和 END 事件。

那么几个问题:

  • 对 proxyRequest.end() 的调用安全吗?也就是说,即使在事件循环之外调用它,proxyResponse 仍然会完成吗?

  • GET 不触发 END 事件是否正常,或者 END 是否在连接堆栈中的某处被捕获?

【问题讨论】:

  • finish 事件似乎按照here 的建议工作

标签: javascript proxy node.js connect coffeescript


【解决方案1】:

我的经验是 request.on('end',) 不会始终被调用,除非它是一个 POST。我怀疑事件(某人发出 http.request)在脚本有机会检测到它之前就结束了。

【讨论】:

  • 我正在努力解决同样的问题。真让人抓狂。
【解决方案2】:

问题不在于end 事件,而在于data 事件。如果客户端发出 GET 请求,则有标头但没有数据。这与 POST 不同,后者是请求者发送数据,因此on("data") 处理程序会被命中。所以(请原谅我的 JS 示例,我对咖啡脚本不太熟悉):

var http = require('http');

// You won't see the output of request.on("data")
http.createServer(function (request, response) {
  request.on("end", function(){
    console.log("here");
  });
  request.on("data", function(data) {
    console.log("I am here");
    console.log(data.toString("utf8"));
  });
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');

如果我对此服务器进行 curl 调用,数据事件永远不会被命中,因为 GET 请求只不过是标题。因此,您的逻辑变为:

// okay setup the request...
// However, the callback doesn't get hit until you
// start writing some data or ending the proxyRequest!
proxyRequest = http.request(options, (proxyResponse) ->
  // So this doesn't get hit yet...
  proxyResponse.on('data', (chunk) ->
   response.write(chunk, 'binary')
  )

  // and this doesn't get hit yet
  proxyResponse.on('end', (chunk) ->
   // which is why your response.on("end") event isn't getting hit yet        
   response.end()
  )

  response.writeHead proxyResponse.statusCode, proxyResponse.headers    
)

// This doesn't get hit!
request.on('data', (chunk) ->
  proxyRequest.write(chunk, 'binary')
)

// So this isn't going to happen until your proxyRequest
// callback handler gets hit, which hasn't happened because
// unlike POST there's no data in your GET request
request.on('end', ->
  proxyRequest.end()
)

// now the proxy request call is finally made, which
// triggers the callback function in your http request setup
proxyRequest.end()

所以是的,由于我刚才提到的逻辑分支,您将不得不手动调用 proxyRequest.end() 来处理 GET 请求。

【讨论】:

  • 使用上面的示例脚本,request.on("end") 回调 is 在 GET 上触发,但 data 事件不是......这让我想到了一些东西连接基础设施内部正在发生时髦......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-24
  • 1970-01-01
  • 1970-01-01
  • 2017-02-06
相关资源
最近更新 更多