2016-09-07 54 views
1

情況如下:Node.js http服務器:POST請求的未讀主體會發生什麼?

HTTP連接選項:連接:保持活動狀態。

  1. HTTP客戶端發送帶有無效驗證的POST請求。 POST請求在內容中有相當數量的內容 - 例如80KB。
  2. HTTP服務器(使用express和http-auth節點模塊)讀取請求頭(但不是主體),並確定此請求不是授權請求,併發送401響應。
  3. 現在身體仍然未被服務器讀取,但由於HTTP連接選項爲Connection:keep-alive,TCP連接未關閉。

現在會發生什麼?未讀機構是否會被放棄,或者應用程序代碼是否必須顯式讀取並放棄它以接收來自當前TCP連接的進一步HTTP請求?

UPDATE

我已經寫了簡單的測試腳本。

客戶:

'use strict'; 

var http = require('http'); 

function doIt() 
{ 
    var postData; 
    (function() 
    { 
     var i, baseData; 
     var dup = 6700; 

     baseData = 'dummy text'; 
     postData = ''; 
     for (i = 0; i < dup; i++) 
      postData += baseData; 
     console.log('data length = ' + postData.length); 
    })(); 

    var agent = new http.Agent(
     { 
      keepAlive: true, 
      keepAliveMsecs: 30000, 
      maxSockets: 1 
     }); 

    var options = 
    { 
     host: 'localhost', 
     port: '9876', 
     path: '/', 
     method: 'POST', 
     headers: 
     { 
      'Content-Type': 'plain/text', 
      'Content-Length': Buffer.byteLength(postData) 
     }, 
     agent: agent 
    }; 

    var count = 1; 
    function doReq() 
    { 
     console.log((count++) + ' ========================='); 
     var req = http.request(options, function (res) 
     { 
      console.log('status code = ' + res.statusCode); 
      console.log('headers', res.headers); 
      res.setEncoding('utf8'); 
      res.on('data', function (chunk) 
      { 
       console.log('Response: ' + chunk); 
      }); 
      res.on('end', function() 
      { 
       setTimeout(doReq, 1000); 
      }); 
     }); 
     req.on('socket', function (socket) 
     { 
      console.log('socket.keepAliveTestId', socket.keepAliveTestId); 
      if (socket.keepAliveTestId === undefined) 
       socket.keepAliveTestId = Date.now(); 
     }); 
     req.on('error', function (err) 
     { 
      console.log('error:', err); 
     }); 
     req.write(postData); 
     req.end(); 
    } 

    doReq(); 
} 

doIt(); 

服務器:

'use strict'; 

var http = require('http'); 
var express = require('express'); 

var app = express(); 
var httpServer = http.createServer(app); 

app.use(function (req, res, next) 
{ 
    console.log(req.headers); 
    setTimeout(function() 
    { 
     next(new Error('test error')); 
    }, 1); 
}); 

app.use(function (err, req, res, next) 
{ 
    console.log('returning'); 
    res.status(401).end(); 
}); 

httpServer.listen(9876); 

通過該測試程序,以下行爲wwas觀察:

隨着連接:保持活動,DUP> = 6700時(也就是說,POST數據的大小> = 67,000字節),服務器不再響應第二個請求。

通過這個,我可以猜測Node.js的http服務器代碼並沒有明確地將剩餘的POST數據吃掉,但是當它通過一個套接字讀取頭來讀取整個POST數據時,它可能會意外地執行它並把它交給http解析器,或者發生類似的事情。

+0

誰說身體永遠不會被讀取?你有什麼參考? – jfriend00

+0

@ jfriend00我的意思是應用程序不會讀取正文。 (也許http模塊實際上讀取它) – zeodtr

+0

因此,看起來你有一個假設,沒有人從TCP套接字讀取身體數據,但你不知道這是否是真的。看來你應該首先弄清楚這是否是真的。如果http庫在內存中排列這些數據(等待它由傳入流中的某人讀取),那麼您已經有了答案。 – jfriend00

回答

0

每個請求都是一個新請求。它與以前的要求和未來要求無關。

爲了保持活躍: 一旦您從服務器響應,下一個請求將來自隊列(僅適用於相同的TCP連接)。

For without keep alive: 它會在您每次向服務器請求時創建連接。

所以你不需要丟棄任何東西,只是響應請求。

+0

問題在於,由於TCP提供了有序的數據包傳輸,如果大量的主體數據被髮送並且沒有人讀取它,那麼它會阻塞下一個可能通過連接發送的請求的TCP連接,並且它具有在另一個請求可以通過同一連接讀取之前避開。 – jfriend00

+0

@ jfriend00我試圖找到相關的代碼,讀取並放棄Node的http源代碼中的剩餘內容,但目前找不到一個。 – zeodtr