質問:
書籍:「サーバサイドJavaScript Node.js入門」の p186 10.4 HTTPクライアントの概要 で
最終的にreq.end() メソッドによって保存されたHTTPリクエストデータがサーバ側に初めて送信されます(図10-9)。
と書いてあるけど、実際動作確認してみるとreq.end()
より前にデータが送られているように見える。記述の間違いじゃないか?
と質問を受けました。
そこで、 http.ClientRequest
のreq.write()
の挙動(どのタイミングでデータは送られるのか)ということを調べました。
回答:
テキストの記載が間違いでした。req.end()
の有無に関係なくreq.write()
の実行によりサーバ側へHTTPリクエストのボディデータは送信されます。
理由:
ソースを確認したら、req.write()
するとソケットに接続していればその時点でソケットにデータを書き込む処理を行っていました。よって req.end()
がなくてもHTTPリクエストのボディデータはサーバ側に送信されます。
じゃなぜ間違えたの?:
下記の様に単純な HTTPクライアントリクエストを行うコードでは、client.write()
がfalse
だったので、どんな状況でも単純に req.write()
では出力バッファに溜り、req.end()
で出力バッファをフラッシュ&送信しているものと思い込んでました。(私の確認不足です。)
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() すれば、実行時に直ちにデータはサーバに送信されます。
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() は、リクエストオブジェクトのソケット接続が完了していれば、直ちにデータをサーバに送信します。ソケットが未接続の場合やエージェントからソケットの割り当てがまだされていない場合は、データは出力バッファに溜まります。
と書くのが正しい表現でした。近日中に正誤表を更新いたします。