nc(netcat)コマンドでHTTPサーバーの気持ちを知る
この記事はFusic Advent Calendar 2017 12日目の記事です。
WEBエンジニアとしていつもお世話になっているApacheやNginxと言った「HTTPサーバーの気持ち」を知ろうと思い立ったので、ncコマンドを使ってHTTPリクエストを受けてHTTPレスポンスを返す一連の流れを体験してみました。
まがいなりにもネットワークスペシャリストなのでネットワーク関連の記事を書こうと思っていましたが、良いネタが思いつかなかったので、今日はレイヤー7で遊ぼうと思います。
ncコマンドで簡易サーバーを立てる
何はともあれ、HTTPを受けるためのサーバーが必要です。 8000番ポートで待ち受けるTCPサーバーをncコマンドで構築します。
while : ; do nc -l 127.0.0.1 8000; done
これでオレオレHTTPサーバ(文字通り)の構築は終わりです。簡単ですね。 もちろんこのサーバーは、同時に1つのリクエストしか処理できません。
ncコマンドはコネクションがクローズすると、プロセスが終了してしまいます。 一々コマンドを再実行してもいいですが、面倒臭いのでwhileで永続化しています。
HTTPリクエストを受けてみる
おもむろにブラウザ(Chromeがおすすめ)を立ち上げて、http://localhost:8000にアクセスしてみます。 おそらく、下記のようなHTTPリクエストが飛んでくるはずです。
$ while : ; do nc -l 127.0.0.1 8000; done GET / HTTP/1.1 Host: localhost:8000 Connection: keep-alive User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36 Upgrade-Insecure-Requests: 1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate, br Accept-Language: ja,en-US;q=0.9,en;q=0.8 Cookie: username-localhost-50080="2|1:0|10:1511168650|24:username-localhost-50080|44:Nzc3OWJmNjE0NTI5NDEzZDk2Y2I2MzU5ZmEwMmE1MDQ=|4279df9a2de706e91212b77f6ef85216f0b7f2f9fb8211e6430c53b5f283b952"
ブラウザにはまだ何も表示されません。 レスポンスを返していないのだから当然ですね。
HTTPレスポンスを返す
いつまでもブラウザを待たせているのもかわいそうなので、そろそろレスポンスを返してあげます。 コンソールに、下記の内容のレスポンスヘッダを返します。
HTTP/1.1 200 OK Server: k-masatany 28.5 (nightly) Content-Type: text/html <!DOCTYPE html> <html> <title>nc server</title> </head> <body>
ここまで入力すると、Chromeを使っていれば、開いているページが真っ白になり、ページタイトルが「nc server」になっているはずです。 Safariだと、Ctrl+DでEOFを送信するまでレンダリングは行われませんでした。
bodyの内容も送る
真っ白なページでは面白くないのでbodyの内容を送ってみましょう。 先ほどの<body>に続いて、下記の内容を書いて行きます。
<div>Hello, HTTP World!</div> <h1>H1 Message</h1> <h2 style="color: red">Red Color Message<h2> <h3>hogehoge</h3>
Chromeでは、タグを閉じるたび、レンダリングが行われます。
404 NotFoundを返してみる
http://localhost:8000/notfoundにアクセスしてみます。 ここにはコンテンツがないので、404を返してみます。 (オレオレHTTPサーバにはそもそもコンテンツがないので全部404なのですが・・・)
HTTP/1.1 404 Not Found Server: k-masatany 28.5 (nightly) Content-Type: text/html <!DOCTYPE html> <html> <title>nc server</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous"> </head> <body> <h1 class="display-1">404 Not Found</h1> <p class="h2">ご指定のページは見つかりませんでした<p>
おっと、文字化けしてますね(しれっとBootstrap適用)。
ページをリロードして、metaタグを追加したレスポンスbodyを再送信します。
HTTP/1.1 404 Not Found Server: k-masatany 28.5 (nightly) Content-Type: text/html <!DOCTYPE html> <html> <meta charset="utf-8"> <title>nc server</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css" integrity="sha384-PsH8R72JQ3SOdhVi3uxftmaW6Vc51MKb0q5P2rRUpPvrszuE4W1povHYgTpBfshb" crossorigin="anonymous"> </head> <body> <h1 class="display-1">404 Not Found</h1> <p class="h2">ご指定のページは見つかりませんでした<p>
日本語も無事表示されました。
404ステータスコードを返しても、bodyにコンテンツを入れていると、描画されてしまうので、 レスポンスボディを消してみます。
HTTP/1.1 404 Not Found Server: k-masatany 28.5 (nightly) Content-Type: text/html ^D # Ctrl+D
ChromeのHTTP ERROR 404ページになりました。 きちんとステータスコードが影響しています。
HTTPで遊んでみて
色々HTTPで遊んでみましたが、各種HTTPヘッダに対する応答をはじめ、オレオレおHTTPサーバーでは様々な機能が使えません。
こんな面倒なことをいつも一瞬でやってくれているHTTPサーバーに感謝を感じる遊びでした。
最後に
忙しくてレスポンスが返せない時は、きちんと503エラーを返しましょう。
HTTP/1.1 503 Service Unavailable Server: k-masatany 28.5 (nightly) Content-Type: text/html ^D # Ctrl+D