2011-06-04 38 views
3

我正在處理一個涉及在另一個服務前使用node.js作爲代理服務器的狡猾計劃。node.js http.request事件流 - 我的END事件發生在哪裏?

簡而言之:

  1. 調度傳入請求靜態文件(如果存在的話)
  2. 否則,將請求調度到另一個服務

我有基礎的工作,但現在試圖讓整個事情與Sencha Connect一起工作,這樣我就可以訪問所有提供的kick-ass中間件。

所有動作都發生在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,proxyResponse是否仍會完成?

  • GET不會觸發END事件,或者END被捕獲到連接堆棧的某個地方是正常的嗎?

+0

'finish'事件似乎按照建議[here](http://stackoverflow.com/a/18255507) – 2015-01-21 14:12:45

回答

4

的問題是少end事件多的data事件。如果客戶端發出GET請求,則會有標頭並且沒有數據。這與請求者發送數據的POST不同,因此on("data")處理程序被擊中。所以,(原諒我的JS例如,我不是那熟悉的CoffeeScript):

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

如果我對這個服務器的捲曲呼叫,數據事件從來沒有被擊中,因爲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請求由於邏輯分支我剛纔提到的。

+0

使用上面的示例腳本,request.on(「end」)回調*被觸發在GET上,但數據事件不是......這讓我覺得連接基礎設施內部發生了一些奇怪的事情...... – 2011-06-04 06:45:23

0

我的經驗是,request.on('end',)不是一致除非它是一個POST,否則將被調用。我懷疑在腳本有機會檢測到該事件之前(發出http.request的人)事件結束。

+1

我正在與這個非常相同的問題摔跤。它很瘋狂。 – Aerik 2014-02-28 16:53:01