LoginSignup
12
8

More than 5 years have passed since last update.

http.ClientRequest の request.write() によるデータ送信のタイミング

Last updated at Posted at 2013-01-17

質問:

書籍:「サーバサイドJavaScript Node.js入門」の p186 10.4 HTTPクライアントの概要 で

最終的にreq.end() メソッドによって保存されたHTTPリクエストデータがサーバ側に初めて送信されます(図10-9)。

と書いてあるけど、実際動作確認してみるとreq.end()より前にデータが送られているように見える。記述の間違いじゃないか?

と質問を受けました。

そこで、 http.ClientRequestreq.write()の挙動(どのタイミングでデータは送られるのか)ということを調べました。

回答:

テキストの記載が間違いでした。req.end()の有無に関係なくreq.write()の実行によりサーバ側へHTTPリクエストのボディデータは送信されます。

理由:

ソースを確認したら、req.write()するとソケットに接続していればその時点でソケットにデータを書き込む処理を行っていました。よって req.end()がなくてもHTTPリクエストのボディデータはサーバ側に送信されます。

じゃなぜ間違えたの?:

下記の様に単純な HTTPクライアントリクエストを行うコードでは、client.write()falseだったので、どんな状況でも単純に req.write()では出力バッファに溜り、req.end()で出力バッファをフラッシュ&送信しているものと思い込んでました。(私の確認不足です。)

request1.js
var http = require('http');
var req = http.request({port:8080, method:'POST'});
console.log(req.write('a')); // false 出力バッファに溜まる
console.log(req.write('b')); // false 出力バッファに溜まる
req.end('c'); // false サーバに送信?

上記 request1.js でclient.write()falseになってデータが出力バッファに溜まっている理由は、req.write()実行時にHTTPクライアントの socket 接続がまだ完了してないからです。

下記コードのように socket 接続が完了した後に client.write() すれば、実行時に直ちにデータはサーバに送信されます。

request2.js
var http = require('http');
var req = http.request({port:8080, method:'POST'});
req.on('socket', function(socket) {
  socket.on('connect', function() {
    console.log(req.write('a')); // true サーバに送信
    console.log(req.write('b')); // true サーバに送信
    req.end('c'); // Chunk終了の"0\r\n\r\n"をサーバに送信
  });
});

よってテキストp186の記述は間違いで、

req.write() は、リクエストオブジェクトのソケット接続が完了していれば、直ちにデータをサーバに送信します。ソケットが未接続の場合やエージェントからソケットの割り当てがまだされていない場合は、データは出力バッファに溜まります。

と書くのが正しい表現でした。近日中に正誤表を更新いたします。

12
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
8