第1回の勉強会で重要だった点の一つは server.close() の挙動でした。 今回は、この server.close() の挙動についての課題です。
A君は、ブラウザで1回閲覧したら HelloWorld のWebサーバが終了するプログラムを作ろうと hello.js を作りました。 だけど Chrome でアクセスすると下のようなエラーになってしまい、プログラムが正常に終了しません。
なぜエラーが発生したのかその理由を記述しなさい。
このプログラムを修正してエラーが発生せずA君がやりたかったプログラムを作りなさい。
gist か ブログかに記載して、URLをメーリングリストに連絡してください。
##提出期限
次回勉強会開催まで。(その前に出そろえば答え合わせでもしましょうか)
> node hello.js
Server running at http://localhost:8080/
net.js:1046
throw new Error('Not running');
^
Error: Not running
at Server.close (net.js:1046:11)
at Server.<anonymous> (/home/ohtsu/hello.js:5:10)
at Server.EventEmitter.emit (events.js:99:17)
at HTTPParser.parser.onIncoming (http.js:1807:12)
at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:111:23)
at Socket.socket.ondata (http.js:1704:22)
at TCP.onread (net.js:403:27)
課題
A君は、ブラウザで1回閲覧したら HelloWorld のWebサーバが終了するプログラムを作ろうと hello.js を作りました。
だけど Chrome でアクセスすると下のようなエラーになってしまい、プログラムが正常に終了しません。
課題1
なぜエラーが発生したのかその理由を記述しなさい。
回答1
2回closeが呼ばれているから。
closeを呼ぶと新規の接続は受け付けなくなるが、既存の接続は生きたままになる。
ブラウザによって挙動は違うかもしれないが、chrome等のブラウザはウェブページにリクエストする際に、該当のページ(ここでは、"/")と既存の接続を使って"/favicon.ico"へ2回アクセスしに来る。
この時の挙動として、
1回目の"/"の時にレスポンスを返した後、server.closeが呼ばれる。
2回目の"/favicon.ico"のリクエストの時に2回目のserver.close()が呼ばれる。★(この時の挙動は以下のように書き換えると分かりやすい。)
この2回目のcloseの時、既に起動していないため、エラーとして起動中ではない事を表すnew Error('Not running');
が投げられる。
出力すると以下のようになり、2回リクエストが来て、server.closeが呼ばれていることが分かる。
課題2
このプログラムを修正してエラーが発生せずA君がやりたかったプログラムを作りなさい。
回答2
server.on('connection')でconnectionイベントをフックして、接続時にcloseさせればclose処理は2回呼ばれなくなる。
あと、最後にかならずリクエストをdestroyして、レスポンスを返した後、明示的に切断するようにしておく。