ブログポストより綺麗(´・ω:;.:...
−−−−
HTTP2サーバーを組み込んだソフトウェアを開発しようと思うと、現在有力な選択肢は nghttp2 と h2o かなって思います。今回は nghttp2 をビルドして得られる libnghttp2_asio.so をリンクしたサーバーと、このサーバーをHTTP2で利用可能なクライアントとして Firefox 35 Developer Edition を使ってみます。
libnghttp2_asio.so のビルドには boost::asio が必要です。
Ubuntu-14.04 などのGNU/Linux環境でaptによらず最新版をまるっとビルドして使いたい場合の例:
git clone git clone --recursive [email protected]:boostorg/boost.git
cd boost
./b2 header
sudo ./b2 --build-type=complete --layout=tagged -j12 install
既に clone 済みからなら git submodule update --init
してから ./b2
する。"/usr/local"以外に入れたければ --prefix=$HOME
とかそういう感じでお忘れなく($HOMEに入れるなら sudo
も要りません)。
./configure
にオプションを明示しないと boost::asio 版のライブラリーはビルドされないので忘れずに。
git clone [email protected]:tatsuhiro-t/nghttp2.git
cd nghttp2
./configure --enable-asio-lib
make -j12
sudo make install
こちらも"/usr/local"以外に入れたければ ./configure
に --prefix=$HOME
などお忘れなく($HOMEに入れるなら install の際に sudo
も要りません)。
また、システムに Jansson や Jemalloc が導入されていれば ./configure
で検出して使ってくれる。Ubuntu-14.04 なら apt-get install libjanson-dev libjemalloc-dev
で用意できる。
凡そ、公式ドキュメントの libnghttp2_asio: High level HTTP/2 C++ library をほぼそのまま参考に、リクエストが来たら標準出力にリクエストのパスを表示する程度、またサーバーの待ち受けアドレスをIPv4系の任意アドレスにするとこんな具合:
#include <nghttp2/asio_http2.h>
#include <iostream>
namespace
{
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
constexpr auto ssl_key = "test.key";
constexpr auto ssl_crt = "test.crt";
}
auto main() -> int
{
http2 server;
server.tls(ssl_key, ssl_crt);
std::cout << "begin listen" << std::endl;
server.listen
( "0.0.0.0"
, 12121
, []
( const std::shared_ptr<request >& req
, const std::shared_ptr<response>& res
)
{
std::cout << "request: " << req->path() << std::endl;
if ( req->path() == "/" || req->path() == "index.html" ) {
res->write_head( 200 );
res->end( file_reader( "index.html" ) );
} else {
res->write_head( 404 );;
res->end("404");
}
}
);
}
ビルド:
g++ -O0 -g std=c++11 -o nghttp2-test1 nghttp2-test1.cxx -lnghttp2_asio
待ち受けアドレスは "*"
にすると IPv6 系になるので、その際は IPv6 のネットワークデバイスのアドレスか、 ::1 でアクセスする必要がある。IPv4で待ち受ける場合は、 localhost 、 127.0.0.1 あるいはIPv4のデバイスのアドレスなど。
Apache/SSL自己証明書の作成とmod sslの設定 など参考にテスト用に "test.key"
と "test.csr"
を用意。
openssl genrsa -aes128 2048 > test.key
openssl req -new -key test.key > test.csr
openssl x509 -in test.csr -days 65535 -req -signkey test.key > test.crt
openssl rsa -in test.key > test_no_passwd.key
mv test_no_passwd.key test.key
適当に準備。
echo 'hello, nghttp2!' > index.html
URL about:config
から network.http.spdy.enabled.http2
を true
にする(初期状態では false
)。
ビルドしたサーバーを起動し、
./ghttp2-test1
HTTP2を利用可能に設定して再起動したFirefoxで、今回のソースの例であれば URL https://localhost:12121/
などアクセスしてみよう。
準備した "index.html"
の内容がブラウザーに表示されれば、 HTTP2 で libnghttp2_asio を使ったサーバーとウェブブラウザーがうまく通信できたという事。未対応のウェブブラウザーではHTTP2のバイナリーフレームを解釈できないのでどうにもならないか、謎のデータが表示される事になる。
サーバーも std::cout
を仕込んであったので、 Firefox からのリクエストに応じて /
や /favicon.ico
のパスを要求された旨を標準出力に示す。もちろん、適当なURLを要求してもブラウザーには 404 が返り、ログにはその要求されたパスが表示される。
ちなみに、 Chromium-38 では chrome://flags/#enable-spdy4 あたりを有効化したらもしかして、と思ったけれども対応できず。今のところ、 HTTP2 を nghttp2 で直接試そうと思ったのなら Firefox を使うのが良さそう。もちろん、 curl-7.35 や wget-1.15 でも HTTP2 の nghttp2 との通信には未対応。
この記事から、 StackEdit というWebブラウザーアプリの Markdown のリアルタイムプレビュー付きのエディターを使ってみている。わりと良い。これまで幾度と無く Blogger 標準機能のエディターにはうんざりしていたものの、 StackEdit には Blogger へのパブリッシュ機能があるので、今回の記事からはとても快適に Blogger へとポストできる。嬉しい(╹◡╹)