資源ヘッダー

資源ヘッダー

[18] 資源ヘッダーは、ファイルsniffing に使われる部分です。

Web における資源ヘッダー

[2] MIME Snffing では、 sniffing に使われるファイルの先頭部分を資源ヘッダー (resource header) といいます >>1

仕様書

MIME 型の sniffing における資源ヘッダー

[4] MIME Sniffing Standard は、 先頭 1445 バイト以上が読み込まれるか、 末尾に到達するか、 利用者エージェント定義の十分な時間が経過するかのいずれか最初の時点での利用可能なデータ全体としています >>1

符号化 sniffing における資源ヘッダー

[19] encoding sniffing には資源ヘッダーという用語はありませんが、 類似の規定が各仕様にあります。


[6] HTML文字符号化宣言 (<meta charset>) は、 HTML文書の最初の 1024 バイト以内に含めなければならないと規定されています >>5

[21] これは著者に対する要件です。

[12] XHR文書応答における HTML の処理 (responseXML) では、 先頭 1024 バイトを使って prescan すると規定されています >>11

[8] HTMLencoding sniffing algorithmprescan では、 利用者エージェント依存としつつも、 先頭 1024 バイトまたは 500 ms 経過までのデータを使うことを勧めています >>7

[9] 当初は 512 バイトとされていましたが、Web互換性のため拡大されました >>16

[20] 処理速度を条件にいれることで、ネットワークの偶然の転送の具合に依存してしまうことになりますが、 読み込みの速度が遅くていつまでも charset sniffing の結果を得られないことを防げます。 navigate に限ってこのような規定があるのは、 incremental rendering が必要であること、 最初のレンダリングまでの処理速度が利用者体験上特に重要であることと、 符号化の変更による修復が可能だからでしょう。

[23] ただしきっちり 1024 バイトに限定することが硬い要件とされているわけではなく、 必要があればそれを超える実装も仕様に違反しません。ローカルファイルの場合など、 すぐに利用できるデータがあって、それを読むことが精度と速度のバランス上有効と思われるなら、 利用できます。

[26] また、 <meta charset> に関する prescan の処理には 1024 バイトの推奨がありますが、その後の頻度解析等の手法には長さの制限がなく、 現実的に 1024 バイトよりも多く読み込む必要がありそうです。 encoding sniffing algorithm

[27] Chromeネットワークから最初に届いたデータに対して文字コードの判定を行います。 >>25

[35] Firefox は最初の 1024 バイトが届いたら prescanchardetng による判定を行います。本構文解析で発見された <meta charset> で異なる結果が得られれば符号化の変更を行います。 すべて読みこんだら改めて chardetng による判定を行い、 異なる結果が得られれば符号化の変更を行います。 >>24

[38] Firefox の挙動は Chrome の挙動だとネットワークの状況依存になってしまい結果が安定しないことへの批判です >>24 が、 体感的には Chrome が最初から正しい符号化レンダリングの開始となることが多いのに対し、 Firefox文字化け状態で読み込んだ後に再読み込みとなることが多く、 Chrome の挙動に分があるように感じられます。

[24] Webブラウザーの挙動を厳密に推定するのは難しく感覚的になってしまいますが、 Chrome と比べると Firefox符号化の変更が必要となって再読み込みすることが多い (資源ヘッダーの処理で正しい判定に失敗することが多い) ように感じられます。 Chrome<meta charset> の prescan で 1024 バイト以上読んでいるのか、 その他の要因によるのかは不明です。

[39] HTML文書の先頭には本文の前に文書型宣言head 要素などが書かれます。 <meta charset> がそこに書かれていればいいのですが、 それが無いときの文字コードの判定に必要な非ASCII文字はそれほど多くありません。 title 要素の中身が主となりますが、それすら ASCII文字のみで構成されることも珍しくありません。 1024バイトは意外と短いのです。

[40] 古い HTML文書が多い Internet Archive に至っては HTML文書の先頭部分に Internet Archive のヘッダーのための要素群が挿入されています。 そのために本文は先頭から非常に遠い部分に追いやられてしまいます。

[41] 非ASCII文字があればいいというものではなく、 データが長ければ長いほど文字コードの判定の精度は高くできます。 1024バイト中の数バイトだけでは正しい判定が難しいことも多いです。

[42] それではデータをすべて使うのが常に正しいかというと、そうとも限りません。 例えば数ギガバイトの動画データが何らかの誤りで文字コードの判定処理に与えられたとき、 それをどこまで処理しても意味はありません。そこまで極端な例でなくとも、 確かに数百メガバイトの ASCII文字の後に非ASCII文字が来るという事例が考えられないわけではありませんが、 そのようなテキストファイル文字コードの判定に失敗することが実装の責めに帰するとは考えにくく、 どちらかといえば無制限の長いデータの処理に伴う性能その他の悪化やセキュリティー問題のおそれを防ぐことの方が重要です。

[43] 推奨される実装戦略:

  • [44] prescan
    • [45] 1024バイトに到達したら打ち切る
    • [46] 500 ms に到達したら打ち切る
  • [47] 頻度解析等の手法
    • [48] データが到着するたびに入力として供給する
    • [50] prescan の方で結果が得られたら打ち切る
    • [49] 確定的結果が得られたらそれを返して打ち切る
    • [51] 途中の暫定結果を返しつつ判定を継続
      • [52] 既に1024バイト以上あれば、1024バイト以上の部分も含め、それを最大まで使ったときに
      • [53] 500 ms に到達したときに
    • [54] 最大 (100MB程度) まで使ったら途中結果を返して打ち切る
    • [55] データの末尾に到達したら結果を返して終了

[14] CSS では、先頭 1024 バイトを使うと規定されています >>13

歴史

[10] MIME sniffingHTML charset sniffing も参照。

[16] [c] (0) Change the limit for where charsets should be given to the fi… (Hixie著, ) https://github.com/whatwg/html/commit/51babfe760a1dbe28c4521b2070e692ac872550a

[25] chardetng: A More Compact Character Encoding Detector for the Legacy Web, Henri Sivonen, , https://hsivonen.fi/chardetng/

その他の資源ヘッダー

[33] BOM は先頭に置けます。

[30] shebang はファイルの先頭に書けます。 ただし Ruby ではもっと後に来ることもあります。 shebang

[32] XML宣言テキスト宣言はファイルの先頭に書けます。 BOM より後になります。

[36] #ABNF はファイルの先頭に書けます。 BOM より後になります。

[37] #VRML, #X3D はファイルの先頭に書けます。

[29] -*- は最初のに書けます。ただしその前に shebang を置けます。 EmacsPython では第2行までですが、 Ruby ではもっと後に来ることもあります。 -*-, ファイル局所変数

[34] Python符号化魔法注釈は、 第1行か第2行に置けます。

[17] Vimモード行は先頭と末尾の5行に書けるとするのが既定値ですが、 変更も可能です。 vim:

[28] Kate Modelines は先頭と末尾の10行に書けます。 kate:

[31] 局所変数群並びはファイルの末尾の3000文字より後、 最後の FORM FEED より後に書けます。

セキュリティー

[22] 資源ヘッダーの処理では、入力が短すぎるとき、長過ぎるとき、無限の長さのときの処置に注意が必要です。 sniffing

関連

sniffing, テキストファイルの先頭

メモ