nghttp2を使用する #1 

HTTP2のライブラリ「nghttp2」を紹介するエントリです。

今回は起動まで行います。
起動するだけなら基本的に公式のGithubに書いてある通りの手順でした。

#Ubuntuインストール

Ubuntu 14.04 LTS
ホスト名は「nghttp2.test」にしました。

必要なモジュールをインストール

```
sudo apt-get install make binutils autoconf  automake autotools-dev libtool pkg-config zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev libjemalloc-dev cython python3.4-dev
```

# nghttp2をgitから取得する

```
sudo apt-get install git
git clone https://github.com/tatsuhiro-t/nghttp2
```

# makeする

コンパイラを入れる。

```
sudo apt-get install g++
sudo apt-get upgrade gcc
sudo apt-get install clang
```

ビルドしてインストールする。

```
cd nghttp2
autoreconf -i
sudo automake
sudo autoconf
./configure
sudo make
sudo make install
```

ライブラリをパスを通すか/usr/lib/へコピーする

```
sudo cp /usr/local/lib/libnghttp2.so.5 /usr/lib/
```

# ドキュメントをビルドする

sphinxをインストールする。

```
sudo apt-get install python3-pip
sudo pip3 install sphinx
```

ドキュメントをmakeする。

```
sudo make html
```

以下のパスにドキュメントがアウトプットされる。

```
doc/manual/html/
```

# HTTP2クライアントとして使う

googleに接続してみる。
「-nas」で時間計測をする。

```
# nghttp -nas https://google.co.jp/

  responseEnd: the  time  when  last  byte of  response  was  received
               relative to connectEnd
 requestStart: the time  just before  first byte  of request  was sent
               relative  to connectEnd.   If  '*' is  shown, this  was
               pushed by server.
      process: responseEnd - requestStart
         code: HTTP status code
         size: number  of  bytes  received as  response  body  without
               inflation.
          URI: request URI

see http://www.w3.org/TR/resource-timing/#processing-model

sorted by 'complete'

responseEnd requestStart  process code size request path
   +52.51ms       +263us  52.25ms  301  222 /
```

「-nv」でフレームの中身を見る。

```
vagrant@nghttp2:~/nghttp2$ nghttp -nv https://google.co.jp/
[  5.015] Connected
[  5.021][NPN] server offers:
          * h2-15
          * h2-14
          * spdy/3.1
          * spdy/3
          * http/1.1
The negotiated protocol: h2-14
[  5.029] recv SETTINGS frame <length=18, flags=0x00, stream_id=0>
          (niv=3)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
          [SETTINGS_MAX_FRAME_SIZE(0x05):16384]
[  5.030] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
          (window_size_increment=983041)
[  5.031] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  5.032] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  5.032] send HEADERS frame <length=36, flags=0x05, stream_id=1>
          ; END_STREAM | END_HEADERS
          (padlen=0)
          ; Open new stream
          :method: GET
          :path: /
          :scheme: https
          :authority: google.co.jp
          accept: */*
          accept-encoding: gzip, deflate
          user-agent: nghttp2/0.7.10-DEV
[  5.036] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  5.082] recv (stream_id=1) :status: 301
[  5.082] recv (stream_id=1) alternate-protocol: 443:quic,p=0.5
[  5.082] recv (stream_id=1) cache-control: public, max-age=2592000
[  5.082] recv (stream_id=1) content-length: 222
[  5.082] recv (stream_id=1) content-type: text/html; charset=UTF-8
[  5.082] recv (stream_id=1) date: Fri, 27 Mar 2015 15:06:34 GMT
[  5.082] recv (stream_id=1) expires: Sun, 26 Apr 2015 15:06:34 GMT
[  5.082] recv (stream_id=1) location: https://www.google.co.jp/
[  5.082] recv (stream_id=1) server: gws
[  5.082] recv (stream_id=1) x-frame-options: SAMEORIGIN
[  5.082] recv (stream_id=1) x-xss-protection: 1; mode=block
[  5.082] recv HEADERS frame <length=202, flags=0x04, stream_id=1>
          ; END_HEADERS
          (padlen=0)
          ; First response header
[  5.082] recv DATA frame <length=222, flags=0x01, stream_id=1>
          ; END_STREAM
[  5.083] recv PING frame <length=8, flags=0x00, stream_id=0>
          (opaque_data=0000000000000000)
[  5.083] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
          (last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])
```

# SSLサーバーとして使う

CommonName「nghttp2.test」で証明書を作成します。パスワードはなし。

```
# openssl genrsa 2048 > server.key
# openssl req -new -key server.key > server.csr
Common Name (e.g. server FQDN or YOUR name) []:nghttp2.test
# openssl x509 -days 3650 -req -signkey server.key < server.csr > server.crt
# rm -f server.csr 
```

ドキュメントルートを作成して、さきほどのnghttp2のドキュメント一式をコピーします。

```
sudo mkdir /var/www
sudo cp -r doc/ /var/www/
```

スレッド数5でドキュメントルートを指定して起動します。

```
// スレッド数5で起動
# nghttpd -n 5 -d "/var/www" 8080 server.key server.crt

IPv4: listen 0.0.0.0:8080
IPv6: listen :::8080
```

クライアントマシンのhostsに「192.168.xxx.xxx nghttp2.test」書きます。
クライアントマシンにserver.crtをインストールしておくか、後でブラウザ警告を無視します。

Chormeで下記のURLに接続します。

```
https://nghttp2.test:8080/doc/manual/html/
```

![nghttp2.png](https://qiita-image-store.s3.amazonaws.com/0/33116/f4c0bb22-1c9d-aab2-e26a-2ea3af2a4c7f.png)