Webパフォーマンス入門: HTTPヘッダ
ヘッダでページの細かなチューニングを
2018年4月13日
著者: Kameerath Kareem
翻訳: 小川 純平
この記事は米Catchpoint Systems社のブログ記事 Web Performance 101: HTTP Headersの翻訳です。
Spelldataは、Catchpointの日本代理店です。
この記事は、Catchpoint Systemsの許可を得て、翻訳しています。
Hypertext Transfer Protocol (HTTP) は、Tim Berners-Leeによって、1991年に初めて導入されました。
最初のバージョンであるHTTP/0.9は、クライアント・サーバ間の、データ伝送の助けとなるように設計されました。
このプロトコルは、TCP接続において、リクエスト・レスポンスモデルで動作しますが、長年にわたって改善や機能拡張が行われ、進化してきました。
最新バージョンはHTTP/2で、Webページのパフォーマンスとスピードを重視した、大きな改善が導入されています。(※)
(※ 訳注:Spelldataの検証では、HTTP/2では、Webサイトの表示速度は高速化できません。)
この記事では、HTTPモデルの重要な部分 ― ヘッダについて、お話します。
先に進む前に、HTTPの動作について理解するために、こちらのブログ記事を読んで下さい。
HTTPヘッダとは
リクエスト・レスポンス構造を構成する、3つの主要なコンポーネントがあります。
これは、以下の3つを含みます。
- 開始行 (start line)
- ヘッダ
- 本文 (body)/コンテント
Requestヘッダ
POST / HTTP/1.1 ← 開始行 Host: localhost:8000 User-Agent: Mozilla/5.0 (Machintosh;… ) Firefox/51.0 Accept: text/html, application/xhtml+xml,…, */*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflat Connection: keep-alive Upgrade-Insecure-Requests: 1 Content-Type: multipart/form-data; boundary=-12656974 Content-Length: 345 ← 空白行 -12656974 ← body部 (more data)
Responseヘッダ
HTTP/1.1 403 Forbidden ← 開始行 Server: Apache Content-Type: text/html; charset=iso-8859-1 Date: Wed, 10 Aug 2016 09:23:25 GMT Keep-alive: timeout=5, max=1000 Connection: keep-alive Age: 3464 Date: Wed, 10 Aug 2016 09:46:25 GMT X-Cache-Info: caching Content-Length: 220 ← 空白行 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML2.0//EN"> ← body部 (more data)
このHTTPメッセージの種類に基づけば、開始行はメソッド、パス、ステータスコード、プロトコルバージョンを含みます。
次の行以降はHTTPヘッダで、コロンで分けられたname-valueペアとして定義されます。
これらのヘッダは、リクエストやレスポンスと一緒に、追加のパラメータを送信するために使われます。
メッセージの本文には、リクエストの際に送信されるデータ、又はレスポンスと共に受信するデータが含まれています。
ヘッダにはいくつか種類があり、これらは利用方法で分けて、大きく分けて4つのカテゴリに分類することができます。
- ジェネラルヘッダ
- リクエストヘッダ
- レスポンスヘッダ
- エンティティヘッダ
ジェネラルヘッダ
リクエスト・レスポンスメッセージの両方で利用できるヘッダで、やり取りされるデータからは独立しています。
よく利用されるジェネラルヘッダとしては、
Cache-Control
Cache-Controlはジェネラルヘッダの一種で、レスポンス→リクエストの繰り返しの中における、キャッシュの設定を行うためのものです。
このディレクティブはヘッダの中で指定され、クライアント・サーバ間においてキャッシュを行う際には、厳格に実装されなければなりません。
例えば、Webページ上の静的ファイルをキャッシュするには、下記のフォーマットを用いてヘッダを定義することができます。
Cache-Control: public, max-age=31536000
Cache Request | 説明 |
---|---|
max-stale[=<seconds>] | クライアントは期限の切れたコンテンツでも受け入れ、秒単位でレスポンスの失効期限を設定することができます。 |
max-age=<seconds> | リソースを最新であると見做す時間を秒数で指定します。 |
min-fresh=<seconds> | 少なくともここで設定された秒数の間は、クライアントはレスポンスが最新 (fresh) であると見做します。 |
no-cache | キャッシュされたコンテンツについて、サーバからクライアントに送信する前に、サーバ側で確認しなければなりません。 |
no-store | リクエスト・レスポンスデータをキャッシュすることを禁止します。 |
no-transform | キャッシュされたコンテンツの変換を禁止します。例えば、容量削減のため、画像形式を変換することなどです。 |
only-if-cached | クライアントはキャッシュされたコンテンツを読み込むのみで、リクエストを送ってオリジンサーバ上の最新のコンテンツを確認したりはしません。 |
Cache Request | 説明 |
---|---|
must-revalidate | 取得したリソースが古いものでないことを確認しなければなりません。 |
no-cache | 上述を参照 |
no-store | 上述を参照 |
no-transform | 上述を参照 |
public | プライベートキャッシュでも、共有キャッシュ(プロキシサーバにおけるキャッシュ)でもレスポンスをキャッシュします。 |
private | 個々のPC・スマートフォンなどの上でのキャッシュです。レスポンスはプライベートキャッシュに保存されますが、共有キャッシュへの保存は禁止されます。 |
proxy-revalidate | 共有キャッシュに適用されます。レスポンスが最新版であることを確認しなければなりません。 |
max-age=<seconds> | 上述を参照 |
s-maxage=<seconds> | 共有キャッシュにおける、キャッシュ有効時間。この値は、プライベートキャッシュには適用されない。 |
他にもいくつか、HTTPキャッシングの標準には属さないヘッダディレクティブがあります。
これはExtension Cache-Controlディレクティブと呼ばれ、例えばimmutableなどがあります。
immutableディレクティブは、レスポンスの本文が変更されていないままであることを示し、クライアントはコンテンツのバリデーションを繰り返さなくて済みます。
Connection
Connectionヘッダは、データ交換が完了した後、HTTPコネクションが開いたままになるように指定するものです。
持続的な接続をセットアップし、後に続くリクエストで再利用できるようにします。
接続を開いたままにするためには、ヘッダが次のフォーマットで送信される必要があります。
Connection: keep-alive
ヘッダディレクティブは、次のものを含みます。
- Keep-alive
- 接続を持続的にし、一度接続が確立されると、後続の全てのリクエストが終わるまで、開いたままになります。
- Close
- この値は、クライアントかサーバに対し、接続を閉じるよう指示するものです。
Transfer-Encoding
Transfer-Encodingは、メッセージの本文のコンテンツを送信する際に使われるフォーマットやエンコーディングを指定するものです。
例えば、ファイルが圧縮されるように指定するには、ヘッダが次のフォーマットで送信される必要があります。
Transfer-Encoding: compress
カンマで区切って、複数のエンコーディングフォーマットを指定することもできます。
このヘッダの値に入るのは、次のディレクティブです。
- chunked
- クライアントやサーバに送信される前に、コンテンツをチャンクに分割します。
- deflate
- deflate 圧縮アルゴリズムを用いて、コンテンツを圧縮します。
- gzip
- Unixのgzipプログラムをベースにした、もう1つの圧縮フォーマットです。
- identity
- コンテンツの圧縮・変更が不要であることを示します。
リクエストヘッダ
これらのヘッダは、要求されたデータのためのパラメータ、又は、リクエストを行うクライアントについての重要な情報を提供するパラメータを定義します。
リクエストヘッダの中で、一般的なものとしては、以下のようなものがあります。
Accept-encoding
このリクエストヘッダは、クライアントがサポートするエンコーディングを指定します。
例えば、クライアントが複数のエンコーディングに対応していることを示す場合、ヘッダのフォーマットは下記のようになります。
Accept-Encoding: deflate, gzip;q=1.0, *;q=0.5
このヘッダに指定できる値は、下記の通りです。
- gzip
- compress
- deflate
- br (Brotliアルゴリズム)
- identity
- * (デフォルトのヘッダの値)
- ;q= (qvaluesの重み付け。各種ファイルの拡張子による読込の優先度設定)
If-match
If-matchリクエストヘッダは条件付きリクエストであることを示します。
このヘッダは、ヘッダで指定された、ETag(リソースに対してユニークな識別子)又はETagの値のリストにマッチした場合にのみ、要求されたレスポンスを返します。
例えば、以下のETagのいずれかを持つサーバからリソースを返す場合、ヘッダは次のようなフォーマットとなります。
("W/"は弱いETagの値を示し、1バイト1バイト正確に確認はしない可能性があります。)
If-Match: W/"67ab43", "54ed21", "7892dd"
If-modified-since
このヘッダも条件付きリクエストです。
サーバは、要求されたリソースが、指定された日付以降に変更されている場合にのみ、そのリソースを返します。
If-Modified-SinceはGETかHEADリクエストでしか使われることはありません。
例えば、2017年10月1日より後に変更されたリクエストを返す場合、ヘッダを次のようなフォーマットで送信します。
If-Modified-Since: Sun, 1 Oct 2017 01:28:00 GMT
リクエストヘッダは、下記の値をデータパラメータとして受け取ることができます。
If-Modified-Since: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
Range
Rangeヘッダはドキュメントやリソースの一部を返すように指定します。
これは、異なる範囲に分割されたコンテンツの一部や、コンテンツの一部分のみをリクエストする際に使われます。
例えば、あるバイトとバイトの間のデータを取得する場合、ヘッダのフォーマットは、下記のようになります。
Range: bytes=200-1000, 2000-6576
1つのコンテンツの、複数の部分をリクエストしたい場合、ヘッダは下記のようなフォーマットになります。
Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>, <range-start>-<range-end>
User-Agent
User-Agentリクエストヘッダはクライアントアプリケーションに関する詳細、例えばソフトウェアのバージョン、アプリケーションタイプ、オペレーティングシステムなどを提供します。
一般的なユーザエージェントヘッダは、下記のようなフォーマットになります。
User-Agent: Mozilla/<version> (<system-information>) <platform> (<platform-details>) <extensions>
下記は、Firefoxのユーザエージェント文字列の例です。
Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail Firefox/firefoxversion
レスポンスヘッダ
これらのヘッダは、送信されてくるレスポンスに関する情報を含みます。
レスポンスヘッダの中で、一般的なものをいくつか、下記に示します。
Accept-Ranges
このレスポンスヘッダは、クライアントにサーバが、範囲指定のリクエストをサポートすることを知らせるものです。
値には、範囲の値の単位を指定します。
例えば、範囲リクエストがバイト単位で送信される場合、ヘッダのフォーマットは下記のようになります。
Accept-Ranges: bytes
ETag
ETagは要求されたリソースに対する一意の識別子です。
キャッシュされたリソースのバージョンを特定しやすくし、リソースの更新の経過を追いやすくします。
Webページ上の画像に対して生成されたetagは、他のレスポンスヘッダのフォーマットと共に送信されます。
ETag: "<etag_value>"
例えば、以下のような記載になります。
etag:51baf2f08d0b59d55196aba274562dcc
Location
Locationレスポンスヘッダは、ページリダイレクトを示すもので、3xxステータスコードのレスポンスと共に送信されます。
ページのリダイレクト先URLを指定します。
ヘッダのフォーマットは下記のようになります。
Location: <url>
Vary
このレスポンスヘッダはリクエストヘッダ群を指定し、キャッシュされたリソースに対する再バリデーションが求められているかを確定します。
例えば、キャッシュされたリソースのモバイルバージョンを配信するには、下記のようにVaryヘッダの値を設定し、リソース配信の前にUser-Agentヘッダを確認するようにします。
Vary: User-Agent
エンティティヘッダ
エンティティヘッダは本文を補足するコンテンツを表すものです。
エンティティヘッダとして一般的なものとしては、次のようなものがあります。
Allow
エンティティヘッダAllowは、要求されたリソースが受け付けることができる、HTTPメソッドを示すために用いられます。
例えば、以下のヘッダの値は、リソースに関連するメソッドを示しています。
Allow: GET, POST, HEAD
Content-Encoding
このエンティティヘッダは、本文で用いられているエンコーディングの種類を示します。
ヘッダは下記のフォーマットで送信されます。
Content-Encoding: gzip
1つのヘッダの中に複数のエンコーディングを含めることもできます。
Content-Encoding: deflate, gzip
Content-Length
このヘッダは、エンティティ、又はメッセージ本文のサイズを示します。
ヘッダのフォーマットは、下記のようになります。
Content-Length: <length>
例:
Content-Length: 3495
ここでは、長さはオクテット数(※)になります。
(※訳注: 8bit単位の数。Byteと同義だが、昨今1MB=1000KBのように10進数で表されることもあるのに対して、オクテットは必ず8bitとなる。)
Expires
Expiresヘッダは、リソースが最新であると考えられる日にち・時間を示します。
例えば、10月10日以降はリソースを古いものとして扱う場合、ヘッダは以下のようになります。
Expires: Wed, 21 Oct 2015 07:28:00 GMT
今回は、様々なHTTPヘッダの分類と、よく使われるヘッダをいくつかご紹介してきました。
これらのヘッダは、キャッシュや、HTTPトランザクションの保護のために必須なものです。
次回の記事では、異なる観点から、HTTPヘッダの役割についてと、ヘッダを用いた際に発生する、パフォーマンスの問題のトラブルシューティングについてお話したいと思います。