Node.js の開発版で http2 標準モジュールを試す

  • 11
    いいね
  • 0
    コメント

概要

2017年8月5日から Node.js の開発版で http2 モジュールが標準機能として利用できるようになりました (プルリクエスト)。記事の執筆時点では実験的な段階にあるので、実行時にフラグを指定する必要があります。Node.js v8.4.0 までには通常の機能として利用できるようにすることが計画されています。

nghttp2 の採用

http2 モジュールの実装には nghttp2 が採用されています。nghttp2 は curl、Apache HTTP Server (mod_http2) で採用されています。

HTTP/2 の普及状況

W3Techs の統計によれば、2017年8月1日時点でHTTP/2 に対応したウェブサイトは全体の15%を超えるとのことです。同じく W3techs のサーバーシェア統計によれば Node.js は全体の0.3%を占めます。

日本国内において大手ホスティングサービスのロリポップが HTTP/2 に対応し、Let's Encrypt を利用することで独自ドメインの SSL/TLS を無料で提供しています。Chrome や Firefox は HTTP/2 通信の際に SSL/TLS を必須としています。

開発版のインストール

Node.js の開発版のインストールには NVS (Node Version Switcher) を使いました。NVS は Windows のためのインストーラーが用意されています。

nvs add nightly
nvs use nightly

実行時のコマンドフラグ

記事の執筆時点で http2 は実験的な段階にあるので、実行時に --expose-http2 フラグを指定する必要があります。

node --expose-http2 client.js

ドキュメント

Node.js のソースコードに含まれる doc/api/http2.md に http2 モジュールの使い方が記載されています。

HTTP クライアント

http2 のマニュアル にいくつかのコードの例が記載されています。HTTP/2 に対応したサイトに対して GET リクエストを送信してみましょう。

client.js
const http2 = require('http2');
const client = http2.connect('https://stackoverflow.com');

const req = client.request({ ':method': 'GET', ':path': '/' });
req.setEncoding('utf8');

req.on('response', (headers, flags) => {
  console.log(headers);
});

let data = '';
req.on('data', (d) => data += d);
req.on('end', () => client.destroy());
req.end();

いろいろな HTTP メソッドやレスポンスを試したいのであれば、https://nghttp2.org/httpbin/ を利用するとよいでしょう。

HTTP サーバー

今度は HTTP サーバーを用意してみましょう。

server.js
const http2 = require('http2');
const fs = require('fs');

const options = {
  key: fs.readFileSync(__dirname + '/server.key'),
  cert: fs.readFileSync(__dirname + '/server.crt')
};

const server = http2.createSecureServer(options);
server.on('stream', (stream, headers) => {
  stream.respond({
    ':status': 200,
    'content-type': 'text/html; charset=utf-8',
  });
  stream.end('hello world!');
});
server.listen(3000);

Chrome や Firefox が SSL/TLS を必須としているので、これらのブラウザーで自己署名証明書を用意します。

その他

自己署名証明書の生成

TLS/SSL の自己署名証明書は次のワンライナーで生成できます。

# https://stackoverflow.com/a/41366949/531320
openssl req -x509 -newkey rsa:4096 -sha256 \
-nodes -keyout server.key -out server.crt \
-subj "/CN=example.com" -days 3650

@std/esm による import

@std/esm を導入すれば import/export が使えるようになります。

import http2 from 'http2';

モジュールバンドラーの Webpack と比べてスクリプトを修正するたびにビルドしなくてすむので手軽です。Yarn で導入するには次のコマンドを実行します。

yarn add @std/esm

コマンドラインからスクリプトを実行するには -r (require) オプションで `std/esm を読み込みます。

node --expose-http2 -r @std/esm client.mjs

デフォルトではスクリプトの拡張子を mjs にする必要があります。js を読み込むことができるようにするには package.json に次の設定を追加する必要があります。

package.json
{
  "@std/esm": { "esm": "js" }
}
node --expose-http2 -r @std/esm client.js