2016-06-07 60 views
0

我想通過restify服務器將上游http.IncomingMessage轉發給客戶端。這是我直到現在纔想到的。它提供轉發功能。但是我認爲這可能導致內存泄漏:處理條件未消耗的http.IncomingMessage

var server = restify.createServer() 

server.get('/test', function(req, res, next) { 
    var upstreamReq = createUpstreamReq() // just creates a http.ClientRequest 

    upstreamReq.on('response', function(upstreamRes) { 
     if (upstreamRes.statusCode === 404) { 
      // (1) I guess this leaks the upstreamRes body ? 
      return next(new restify.errors.NotFoundError()) 
     } 
     if (upstreamRes.statusCode !== 200) { 
      // (2) is there a better way than pipeing the response to /dev/null? 
      // I guess the advantage of this approach is that we can reuse the connection (not closed) ? 
      upstreamRes.pipe(fs.createWriteStream('/dev/null')) 
      return next(new restify.errors.InternalServerError()) 
     } 
     res.setHeader('Content-Type', upstreamRes.header('Content-Type')) 
     res.setHeader('Content-Length', upstreamRes.header('Content-Length')) 
     upstreamRes.pipe(res) 
     return next() 
    }) 

    upstreamReq.end() 
}) 
  • 我假定在上游404這個碼的情況下漏upstreamRes體(1),因爲它從未消耗(無pipe(somewhere))?
  • 不應該泄漏upstreamRes正文的一個明顯的解決方案(2)是將其管道到/dev/null。有沒有替代/更好的解決方案?
+0

雖然措辭良好,但這是一個比特定問題更多的代碼審查。 – HeadCode

+0

@HeadCode我改變它更接近一個問題。 –

回答

0

看來,我跳過了一個重要的部分文檔中關於http.ClientRequest

如果不加「響應」處理程序,那麼響應將完全 丟棄。但是,如果添加'響應'事件處理程序,那麼必須通過調用 response.read()(每當發生「可讀」事件時)或通過添加一個 '數據'來響應對象時,處理程序,或通過調用.resume()方法。在消耗數據爲 之前,「結束」事件不會觸發。此外,直到數據被讀取 它會消耗內存,最終可能會導致'處理出內存錯誤' 。

https://nodejs.org/api/http.html#http_class_http_clientrequest

因此正確答案似乎是:

  • 你需要的,如果你不感興趣的返回的消耗爲每http.ClientRequest
  • 的響應(http.IncomingMessage)數據推薦的方法是撥打upstreamRes.resume()。即使沒有連接消費者,這也會啓動數據流。
+0

這是一個很好的完整答案。我要刪除我的回覆。 – HeadCode