[最速] HTTP/2 で Hello World! するまでの手順

2014年6月にHTTP/2の[13番目のドラフト](http://tools.ietf.org/html/draft-ietf-httpbis-http2-13)が公開され、来年にはRFC化の見通しとのことでHTTP/2の機運が高まってきています。

HTTP/2の世界を体感すべく、HTTP/2プロトコルでHello World!を表示するまでの手順をまとめました。

最速と名をうちましたが実のところそこそこ長い道のりですので予めご了承ください。

# 方針

簡単と思われる方法を探した結果、以下の構成にしました。

**クライアント**

2014年7月現在、Google ChromeではHTTP/2を有効にすることはできませんが、Chromeの開発版である[Chrome Canary](http://www.google.co.jp/intl/ja/chrome/browser/canary.html)を使えばHTTP/2を有効できます。

Mac Book Proに[Chrome Canary](http://www.google.co.jp/intl/ja/chrome/browser/canary.html)をインストールします。CanaryはChromeの開発版でMac用のdmgパッケージが提供されているのでインストールは簡単です。

なお、クライアントはnghttp2付属のCLIクライアントを使うともっとカジュアルに確認できるのですが、今回はブラウザを使いました。


**サーバ**

VirtualBoxにUbuntuをインストールし、[nghttp2](https://github.com/tatsuhiro-t/nghttp2)をインストールする。

# クライアントの準備

CanaryのページからMac版のバイナリをインストールしてください。既存のChromeとはインストールフォルダは別なので設定が混ざるようなことはありません(※開発版なので予期せぬ挙動が無いとは言い切れませんが...)

なお、CanaryはデフォルトではHTTP/2は無効なので、以下のようにコマンドラインから起動することでHTTP/2が有効化されます。

```
$ /Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary --enable-spdy4
```


アドレスバーから`chrome://net-internals/#spdy`へアクセスし、Next Protocolsに`h2-13`が含まれていれば有効になってます。

![net-internals 2.png](https://qiita-image-store.s3.amazonaws.com/0/13877/3fbbc395-1cfd-30ba-e360-d5a4e2d675d9.png)


# サーバの準備

Ubuntu上でnghttp2をbuildします。手順は[nghttp2 を ubuntu でビルド](http://qiita.com/Jxck_/items/ec8bda302d816505a133)のとおりです。

nghttpdはHTTPモードとSSLモードの2パターンの起動モードを選択できます。本書ではSSLモードで起動させます。なおHTTPモードを選択しない理由は、Canary(38.0.2094.0 canary)ではnghttpdのHTTPモードとHTTP/2の接続を確立できなかったためです。原因は深堀りしていませんが、今後のバージョンではうまくいくかもしれません。

以下のとおりprivate keyとサーバ証明書を作成します。

```
# 秘密鍵(private.key)と証明書要求(server.csr)を作成
$ openssl genrsa -des3 -passout pass:x -out server.pass.key 2048
...
$ openssl rsa -passin pass:x -in server.pass.key -out server.key
writing RSA key
$ rm server.pass.key
$ openssl req -new -key server.key -out server.csr
...
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:California
...
A challenge password []:
...

# サーバ証明書(server.crt)を作成
$ openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
```

サーバを以下のとおり起動します。HTTP/2のやり取りを見たいので`-v`オプションをつけます。

```
$ nghttpd -v 8080 server.key server.crt
IPv4: listen on port 8080
IPv6: listen on port 8080
```

最後に、MacのVirtualBox側でポートフォワードを有効にし、Mac側からアクセスできるようにしておきます。8888/tcpをサーバの8080/tcpにマップしました。

![sc1 2.png](https://qiita-image-store.s3.amazonaws.com/0/13877/f47067b6-27ea-eb06-6122-d95bd760c2ba.png)

# Hello, World!

`nghttpd`は起動するとカレントディレクトリを公開しますので、サーバのカレントディレクトリにindex.htmlを置きます。

```html
<html>
<body>Hello, World!</body>
</html>
```

Chrome Canaryで`https://localhost:8888/index.html`にアクセスしHello, World!が表示されれば成功です!

# HTTP/2のバイナリフレーミングを確認する

Hello, Worldを表示させた次は、HTTP/2のプロトコルの中心であるバイナリフレーミングを覗き見てみましょう。

一番簡単なのは、`chrome://net-internals#SPDY`を参照するやり方で、現在のセッションのプロトコルバージョン始め、HTTP/2のフレームのやり取りも様々確認できます。Protocol Negotiatedがh2-13になってれば成功してます。

![cons 2.png](https://qiita-image-store.s3.amazonaws.com/0/13877/1c15b3d4-d700-6cb4-77fb-2b6b90078944.png)

パケットレベルで見たい人はWireshark使いましょう。ただ少し大変で、HTTP/2のバイナリを解釈してくれるには開発版をbuildする必要があります。詳細は[Wiresharkをubuntuでbuildする](http://qiita.com/niku4i/items/075b0f68c9d15a932be9)にまとめました。

# 応用編

次なるアクションとしては、

* **HTTP/1.1 vs HTTP/2のリクエスト多重化** を確認するために、index.htmlに`<img>`タグや`<link>`タグでjs,cssなどを沢山埋め込み、Chromeのdeveloper consoleのリソース取得のtimelineを見てみるとか。HTTP/1.1では1FQDNあたり6同時接続制限がありましたが、HTTP/2の多重化により解決してるか確認する
* **サーバプッシュ**を試してみる
* RailsをHTTP/2でproxyしてみる

などが面白そうです。

# まとめ

HTTP/2プロトコル上でHello, Worldをブラウザに表示しました。

タイトルに最速と打ちましたが、実のところHello, Worldまでの道のりはまだまだ長かったです。今後RFCが公開され各種ツールの開発が進めばrpm等のバイナリパッケージを使って導入が簡単になっていくとおもいます。

# 参考

* [nghttp2 を ubuntu でビルド](http://qiita.com/Jxck_/items/ec8bda302d816505a133)
* [h2-13日本語訳](http://summerwind.jp/docs/draft-ietf-httpbis-http2-13/)
* [Creating a Self-Signed SSL Certificate](https://devcenter.heroku.com/articles/ssl-certificate-self)