これは、nginx Advent Calendar 2016の8日目の記事です。
103 Early Hints
先日の「Apache mod_http2 で 103 EarlyHints を試す」という記事でも書きましたが。軽くおさらい。
103 Early Hintsは、@kazuho氏によって提案されている仕様です。すでに Individual-Draftが提出されています。
https://tools.ietf.org/html/draft-kazuho-early-hints-status-code-00
IETF97でも仕様についての議論が行われており、その際のスライドを見ると分かりやすいかと思います。
https://www.ietf.org/proceedings/97/slides/slides-97-httpbis-sessb-early-hints-00.pdf
ステータスコードはコンテンツの生成が終わったあとに決定されるため、コンテンツの生成が終わるまでHTTPレスポンスは送信開始できません(1行目がステータスコードのため)。
103ステータスコードのレスポンスは本来のHTTPレスポンスに先んじて送信できるので、先行してHTTPレスポンスヘッダを送信することができます。たとえばLinkヘッダでPreloadを先に送信すれば今後必要になるリソースをより早くクライアントに知らせることができます。
前回の103ステータスコードを用いたmod_http2の実験では、103ステータスコードを返すサーバはモックサーバを立てましたが今回はNginxモジュールを書いてみました。(試験実装なので怪しいとは思います)
ngx_http_early_hints
試験実装ですがngx_http_early_hints モジュールとして、すでに公開済になります。
https://github.com/flano-yuki/ngx_http_early_hints
以下のように、locationディレクティブに add_early_header を宣言すると、マッチする際に103ステータスのレスポンスを返すようになります。
location /103.html { add_early_header "Link" "</main.css>;rel=preload"; }
実際にHTTPリクエストを送信してみると以下のように103スレータスのレスポンスがまず送信されます。
(NGX_HTTP_ACCESS_PHASEでフックしてるので、コンテンツの生成より早いタイミングで送信されます)
vagrant@vagrant:~$ telnet localhost 80 Connected to localhost. Escape character is '^]'. GET /103.html HTTP/1.1 host:localhost
HTTP/1.1 103 Early Hints Link: </main.css>;rel=preload HTTP/1.1 200 OK Server: nginx/1.11.6 Date: Wed, 07 Dec 2016 13:29:12 GMT Content-Type: text/html Content-Length: 22 Last-Modified: Wed, 07 Dec 2016 13:28:44 GMT Connection: keep-alive ETag: "58480e8c-16" Accept-Ranges: bytes This is main contents
あとがき
Nginxモジュールを初めて書くので、お作法がだいぶわからなかったのですが、下記サイトが非常に参考になりました。ありがとうございます。
- cubicdaiya/ngx_http_hello_world https://github.com/cubicdaiya/ngx_http_hello_world
- ngx_mrubyから学ぶnginxモジュールの作り方 http://blog.matsumoto-r.jp/?p=2841
実用に足るかはわかりませんが、エラーハンドリング、HTTP/2のサポート、複数add_early_headerのサポート、ほかモジュールとの併用検証など進めていければと思います。