要約:Resource Timing の定義する responseStart イベントは informational response (1xx) をレスポンスの開始点として扱うので、1xx を返すアプリケーションで responseStart を記録する場合は注意が必要。

Resource Timing

Resource Timing 仕様はリソース読み込みに関する様々なイベントのタイムスタンプを取得するための JavaScript API を定義している。本記事執筆時点では以下のイベントが定義されている。各イベントの詳細は MDN などを見てください。

[Exposed=(Window,Worker)]
interface PerformanceResourceTiming : PerformanceEntry {
    readonly        attribute DOMString           initiatorType;
    readonly        attribute DOMString           nextHopProtocol;
    readonly        attribute DOMHighResTimeStamp workerStart;
    readonly        attribute DOMHighResTimeStamp redirectStart;
    readonly        attribute DOMHighResTimeStamp redirectEnd;
    readonly        attribute DOMHighResTimeStamp fetchStart;
    readonly        attribute DOMHighResTimeStamp domainLookupStart;
    readonly        attribute DOMHighResTimeStamp domainLookupEnd;
    readonly        attribute DOMHighResTimeStamp connectStart;
    readonly        attribute DOMHighResTimeStamp connectEnd;
    readonly        attribute DOMHighResTimeStamp secureConnectionStart;
    readonly        attribute DOMHighResTimeStamp requestStart;
    readonly        attribute DOMHighResTimeStamp responseStart;
    readonly        attribute DOMHighResTimeStamp responseEnd;
    readonly        attribute unsigned long long  transferSize;
    readonly        attribute unsigned long long  encodedBodySize;
    readonly        attribute unsigned long long  decodedBodySize;
    [Default] object toJSON();
};

各イベントはざっくり以下のようにマッピングされる (図は Resource Timing の仕様より引用)

表紙

今回はこのうちの responseStart に関する話。responseStart は HTTP レスポンスヘッダを受信して処理し始めたタイミングを表す。これは TTFB (Time To First Byte) とも呼ばれる。仕様では次のように定義されている。

The time immediately after the user agent’s HTTP parser receives the first byte of the response (e.g. frame header bytes for HTTP/2, or response status line for HTTP/1.x) from relevant application caches, or from local resources or from the server, if the resource passes the timing allow check algorithm.

4.3 The PerformanceResourceTiming Interface - responseStart

Informational Response (1xx)

HTTP では最終的なレスポンスを返す前に補足情報を載せたレスポンスを返すことができる。このレスポンスには HTTP ステータスコード 1xx が使われる。1xx のレスポンスは informational response と呼ばれ、現在以下のものが定義されている。

  • 100 Continue : リクエストを受信中で、完了次第処理を継続することをクライアントに通知する。
  • 101 Switching Protocols : プロトコルの切り替えをクライアントに要求する。WebSocket などで使われる。
  • 102 Processing : リクエストが処理中であることをクライアントに通知する。
  • 103 Early Hints : preload などのためのヒントをクライアントに与える。現時点ではまだどのブラウザも実装していない。

Informational response は最終 response (これを non-informational response と呼ぶことにする) に先立って送られてくる。例えば、

1xx --> 1xx --> ... --> 1xx --> 200

みたくなる。Informational response については一つ前の記事でも触れたのでそちらも見てください。

responseStart と Informational Response

informational response (1xx) を受信した場合、responseStart はそれの first byte をレスポンスの開始点として扱う。つまり

1xx --> 1xx --> ... --> 1xx --> <responseStart> 200 <responseEnd>

ではなく

<responseStart> 1xx --> 1xx --> ... --> 1xx --> 200 <responseEnd>

みたくなる。仕様には以下のように記載されている。

NOTE

… snip …

For fetches composed of multiple requests (e.g. preflights, authentication challenge-response, redirects, and so on), the reported responseStart value is that of the last request. In the case where more than one response is available for a request, due to an Informational 1xx response, the reported responseStart value is that of the first response to the last request.

4.3 The PerformanceResourceTiming Interface - responseStart

以上より、もし 1xx を返すアプリケーションで responseStart を記録する場合は注意が必要になる。200 の start と end を記録しているつもりが 1xx を含んだ時間を記録しているかもしれない。現在の Resource Timing 仕様には non-informational response の first byte の時間を取る方法は定義されていません。

ただ現状 1xx を使っていてさらに Resource Timing でメトリクスを取っているケースはほとんどないだろうし、これが問題になることはまずないと思います。一方、もし今後 103 Early Hints が実装されて広く使われるようになったら問題になるかもしれません。