We're looking for a user researcher to understand the needs of developers and designers. Is this you or someone you know? Check out the post: https://mzl.la/2IGzdXS

HTTP は、 HTML 文書などのリソースを取り出すことを可能にするプロトコルです。これはウェブにおけるデータ交換の基礎をなすクライアントサーバープロトコルであり、リクエストは受け取り者 (一般にはウェブブラウザー) が生成します。文書全体は、テキスト、レイアウトの定義、画像、動画、スクリプトなど、取り込まれたさまざまなサブ文書から再構成されます。

ウェブの文書は複数のリソースの組み合わせ

クライアントとサーバーは、(データの流れとは対照的に) 個々のメッセージを交換することによって通信します。クライアント (通常はウェブブラウザー) が送信するメッセージはリクエスト (要求) と呼ばれます。また、サーバーが回答として送信するメッセージはレスポンス (応答) と呼ばれます。

HTTP はアプリケーション層のプロトコルであり、 TCP (トランスポート層) や IP (ネットワーク層) やプレゼンテーション層以下の上の階層に当たります。1990 年代初頭に設計された HTTP は、時間をかけて進化した拡張可能なプロトコルです。 HTTP は、 TCP または TLS (暗号化された TCP 接続) を使用して送信されるアプリケーション層のプロトコルですが、理論上は信頼性のある任意のトランスポート層プロトコルを使用できます。HTTP は拡張性があるため、ハイパーテキスト文書だけでなく画像や動画の取り込みや、 HTML フォームの入力結果などをクライアントからサーバーへ送信することもできます。また、要求に応じてウェブページを更新するために、文書の一部を取り込むこともできます。

HTTP ベースシステムの構成要素

HTTP はクライアントサーバープロトコルであり、リクエストはユーザーエージェント (または代理のプロキシ) というひとつの実体から送信されます。ほとんどの場合、ユーザーエージェントはウェブブラウザーですが、例えば検索エンジンのインデックスを収集および保守するためにウェブをクロールするロボットなど、どれでもクライアントになることができます。

個々のリクエストはサーバーに送信され、処理した後に レスポンス と呼ばれる回答を提供します。リクエストとレスポンスの間には、例えばゲートウェイやキャッシュなどの様々な操作を行う、まとめてプロキシサーバーと呼ばれるいくつもの実体が存在しています。

クライアントとサーバーの連鎖

実際はブラウザーとサーバーの間に、ルーターやモデムなどリクエストを扱うコンピューターがさらに存在します。ウェブが階層構造で設計されたおかげで、これらはネットワークやトランスポート層の中に隠されています。 HTTP はアプリケーション層の最上位に存在します。ネットワークの問題を診断することは重要ですが、 HTTP を説明する際に下層のことはほとんど重要ではありません。

クライアント: ユーザーエージェント

ユーザーエージェントは、ユーザのために働くツールです。この役割は主に、ウェブブラウザーが担います。ただし、エンジニアや自身のアプリケーションをデバッグするウェブ開発者が使用するプログラムのような例外もあります。

ブラウザーは常に、リクエストを生成する実体です。サーバーにはなりません (もっとも、サーバーが生成するメッセージをシミュレートする仕組みが近年追加されましたが)。

ウェブページを提供するため、ブラウザーはページから HTML 文書を取り込む最初のリクエストを送信します。このファイルを解析して、実行するスクリプト、表示するレイアウトの情報 (CSS)、ページに含まれるサブリソース (通常、画像や動画) に対応する追加のリクエストを発行します。そして、ウェブブラウザーはこれらのリソースを混ぜ合わせて、完全な文書であるウェブページをユーザーに提供します。ブラウザーによって実行されるスクリプトが後の段階でさらにリソースを取り込んで、それに応じてブラウザーがウェブページを更新することがあります。

ウェブページは、ハイパーテキスト文書です。これは表示されているテキストの一部が新たなウェブページの取り込みを (通常、マウスのクリックによって) 発生させるリンクであり、ユーザーがユーザーエージェントを導いてウェブ内を移動できるということです。ブラウザーはこれらの導きを HTTP リクエストに変換して、さらにユーザーへ明確な応答を返すために HTTP レスポンスを解釈します。

ウェブサーバー

通信路の反対側には、クライアントの要求に応じて文書を提供するサーバーがいます。サーバーは、実質 1 台だけのマシンとして見えます。これは、実際は複数のサーバーの集合体であるかもしれないためであり、これらは負荷 (負荷分散)、あるいは他のコンピューター (キャッシュ、データベースサーバー、電子商取引サーバーなど) に問い合わせを行う複雑なひとまとまりのソフトウェアを分け合って、要求に応じて全面的または部分的に文書を生成しています。

サーバーは 1 台のマシンである必要性はありませんが、複数のサーバーを同じマシンで運用することができます。 HTTP/1.1 と Host ヘッダーによって、同じ IP アドレスを共有できます。

プロキシ

ウェブブラウザーとウェブサーバーの間では、多数のコンピューターや機器が HTTP メッセージを中継します。ウェブスタックは階層構造であるため、これらの処理のほとんどはトランスポート層、ネットワーク層、物理層のいずれかで行われ、 HTTP 層から見れば透過的であり、パフォーマンスにかなりの影響を与えます。アプリケーション層で行われる処理は、通常プロキシと呼ばれます。これらは透過的である場合とそうでない場合(プロキシを通過するときにリクエストを変更する場合)があり、さまざまな機能を実行します。

  • キャッシュ (キャッシュは共用、あるいはブラウザーキャッシュのように個人用にできます)
  • フィルタリング (アンチウィルススキャンやペアレンタルコントロールなど)
  • 負荷分散 (複数のサーバーが別々のリクエストに対応できるようにする)
  • 認証 (さまざまなリソースへのアクセスを制御する)
  • ログ記録 (履歴情報の保管を可能にする)

HTTP の基本方針

HTTP はシンプル

HTTP/2 で HTTP メッセージをフレーム内にカプセル化することにより複雑さが増したにもかかわらず、 HTTP は全体的にシンプルで人間が読めるように設計されています。 HTTP メッセージは人間が読んで理解することができ、開発者によるテストを容易にしています。また、初心者に対する複雑さも軽減します。

HTTP は拡張可能

HTTP/1.0 で導入された HTTP ヘッダーによって、プロトコルの拡張や実験が容易になりました。新しい機能であっても、クライアントとサーバーが新たなヘッダーの意味について単純な合意があれば導入できます。

HTTP はステートレスであるがセッションレスではない

HTTP はステートレスです。同じコネクション上であっても、連続的に実行される 2 つのリクエスト間に関係性はありません。これは電子商取引のショッピングバスケットなどのように、ユーザーが一貫した方法で特定のページと対話したいときに直接問題になります。しかし HTTP の核心がステートレスであっても、 HTTP Cookie によってステートフルなセッションを実現できます。ヘッダーの拡張性を利用して、ワークフローに HTTP Cookie が追加されれば、それぞれの HTTP リクエストが同じ状況や同じ状態を共有するためにセッションを作成できるようになります。

HTTP とコネクション

コネクションはトランスポート層で制御されますので、 HTTP の範囲から根本的に外れています。 HTTP は下層のプロトコルがコネクションベースであることに依存はせず、信頼性がある、つまりメッセージを失わないこと(少なくともエラーを表示すること)だけを要求します。インターネットでもっとも一般的な 2 つのトランスポートプロトコルでは、 TCP には信頼性があり、 UDP には信頼性がありません。 HTTP は、常にコネクションが必要ではないとしても、コネクションベースである TCP 標準に従い依存しています。

HTTP/1.0 はそれぞれのリクエスト/レスポンスの交換ごとに TCP コネクションを開いていたため、2 つの欠点が発生していました。コネクションを開くときにいくつかのメッセージのやり取りが必要であるために遅くなります。しかし、メッセージを複数送信したり定期的に送信したりすると効率的になっていきます。ウォーム状態のコネクションはより効率的、コールド状態のコネクションは非効率的です。

この欠点を軽減するため、 HTTP/1.1 でパイプライン (実装が難しいことが立証されました) や持続的接続を導入しました。 Connection ヘッダーを使用して、下層の TCP コネクションを部分的に制御できます。 HTTP/2 はひとつのコネクションに複数のメッセージを多重化するように進化しました。コネクションををウォーム状態に保つのに役立ち、効率が向上します。

より HTTP に適したトランスポートプロトコルを設計する実験が進んでいます。たとえば Google は、より信頼性があり効率的なトランスポート層プロトコルを提供するため、 UDP 上に構築する QUIC の実験を行っています。

HTTP が制御できること

HTTP の拡張性により時間をかけて、ウェブの制御性や機能性が向上できました。キャッシュや認証の方法は、 HTTP の草創期から取り扱われてきた機能です。対照的に、オリジン制約を緩和する機能は2010年代にようやく追加されました。

HTTP で制御できる一般的な機能は以下のとおりです。

  • キャッシュ
    文書をどのようにキャッシュするかを、 HTTP で制御できます。サーバーはプロキシやクライアントに対して、何をどれだけの間キャッシュするかを指示できます。クライアントは中間のキャッシュプロキシに対して、保存されている文書を無視するよう指示できます。
  • オリジン制約の緩和
    のぞき見や他のプライバシー侵害を避けるため、ウェブブラウザーはウェブサイト間を厳密に分割するよう強制しています。同一オリジンのページだけが、ウェブページの情報すべてにアクセスできます。この制約はサーバーにとって負担になりますが、 HTTP ヘッダーでサーバーサイドの厳密な分割を緩和できます。これにより、さまざまなドメインを情報源とした情報の寄せ集めの文書を作成できます (しかし、このようにするセキュリティ上の理由があります)。
  • 認証
    特定のユーザーしかアクセスできないように保護されたページがあるでしょう。基本的な認証は HTTP が提供しており、 WWW-Authenticate などのヘッダーを使用するか、 HTTP Cookie を使用した特別なセッションを設定するかします。
  • プロキシとトンネリング
    サーバーやクライアントがイントラネット内に配置されて、本当の IP アドレスがほかから見えなくなっていることがよくあります。このネットワーク境界を渡るため、HTTP リクエストはプロキシを通過します。すべてのプロキシが HTTP プロキシであるとは限りません。たとえば、 SOCKS プロトコルはよりより低い層で動作します。ほかにも FTP などがそれらのプロキシで処理されることがあります。
  • セッション
    HTTP Cookie を使用して、リクエストとサーバーのセッションを関連付けできます。これにより HTTP がステートレスプロトコルであるにもかかわらず、セッションを作成できます。これは電子商取引のショッピングバスケットだけでなく、出力内容にユーザー設定を適用できるサイトでも有用です。

HTTP のフロー

クライアントがサーバー (最終目的地のサーバーまたは中間のプロキシ) と通信したいとき、クライアントは以下の段階を踏みます。

  1. TCP コネクションを開く: TCP コネクションはひとつまたは複数のリクエストを送信したり、回答を受け取ったりするために使用します。クライアントは新しいコネクションを開く、既存のコネクションを再使用する、あるいはサーバーに対して複数の TCP コネクションを開くことができます。
  2. HTTP メッセージを送信する: HTTP メッセージを (HTTP/2 より前) は人間が読むことができます。HTTP/2 では単純なメッセージがフレーム内にカプセル化されており、直接読むことが不可能になりましたが、原理は変わっていません。
    GET / HTTP/1.1
    Host: developer.mozilla.org
    Accept-Language: fr
  3. サーバーから送信されたレスポンスを読み取る:
    HTTP/1.1 200 OK
    Date: Sat, 09 Oct 2010 14:28:02 GMT
    Server: Apache
    Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
    ETag: "51142bc1-7449-479b075b2891b"
    Accept-Ranges: bytes
    Content-Length: 29769
    Content-Type: text/html
    
    <!DOCTYPE html... (ここに、要求した 29769 バイトのウェブページがある)
  4. 次のリクエストのために、コネクションを閉じるか再使用する

HTTP パイプラインが有効である場合は、最初のレスポンスが完全に返るのを待たずに複数のリクエストを送信できます。 HTTP パイプラインは既存のネットワークで実装するのが難しいことが立証されており、古いソフトウェアと最新バージョンのソフトウェアが共存しています。 HTTP パイプラインは、 HTTP/2 でフレーム内にリクエストを強力に多重化する機能によって置き換えられました。

HTTP メッセージ

HTTP/1.1 以前の HTTP メッセージは、人間が読むことができます。HTTP/2 ではこれらのメッセージが新たなバイナリ構造に埋め込まれており、ヘッダーの圧縮や多重化といった最適化が可能になりました。本来の HTTP メッセージの部分だけがこのバージョンの HTTP で送信されていても、各メッセージの意味は変わっておらず、クライアントは本来の HTTP/1.1 メッセージを (事実上) 再構成します。したがって、HTTP/2 メッセージを HTTP/1.1 形式で理解することは役に立ちます。

HTTP メッセージはリクエストとレスポンスの 2 種類あり、それぞれ固有の形式になっています。

リクエスト

HTTP リクエストの例です。

A basic HTTP request

リクエストは以下の要素で構成されます。

  • HTTP メソッド。通常、クライアントが実行したい操作を定義する GETPOST のような動詞か、OPTIONSHEAD のような名詞です。一般的にクライアントはリソースを取り込む (GET を使用) か HTML フォーム の値を送信する (POST を使用) ことを望みますが、場合によってはほかの操作が必要になります。
  • 取り込むリソースのパス。状況から明らかであればリソースの URL はこの要素から取り除かれます。たとえばプロトコル (http://)、ドメイン (ここでは developer.mozilla.org)、TCP ポート (ここでは 80) が取り除かれます。
  • HTTP プロトコルのバージョン。
  • サーバーに追加の情報を与える任意の ヘッダー
  • POST のようなメソッドではレスポンスと同様に、送信するリソースを包含したボディがあります。

レスポンス

レスポンスの例です。

レスポンスは以下の要素で構成されます。

  • 準拠する HTTP プロトコルのバージョン。
  • ステータスコード。リクエストが成功したか否か、およびその理由を示します。
  • ステータスメッセージ。ステータスコードの簡単な説明ですが、権威はありません。
  • リクエストと同様の HTTP ヘッダー
  • (省略可)リソースを含む本文。

HTTP に基づく API

最もよく使われている最上位の HTTP に基づく API は XMLHttpRequest API で、user agentとサーバーの間でデータを交換するために使用することができます。

他の API、 server-sent events は、サーバーがクライアントにイベントを送信することができる一方通行のサービスで、 HTTP をトランスポートの仕組みとして利用しています。クライアントのブラウザーは HTTP ストリームに届くメッセージを自動的に適切な Event オブジェクトに変換し、もしイベントのが分かればその型に登録されているイベントハンドラーに配信し、型に対してイベントハンドラーが設定されていない場合は、 onmessage イベントハンドラーに配信します。

まとめ

HTTP は容易に使用できる、拡張可能なプロトコルです。クライアントサーバー構造と単純にヘッダーを追加できる機能性を組み合わせて、 HTTP はウェブの機能拡張に合わせて進化できます。

HTTP/2 でパフォーマンスを向上するため、フレーム内に HTTP メッセージを埋め込むことにより複雑さがいくらか増しましたが、メッセージの基本的な構造は HTTP/1.0 から同じままです。セッションのフローは依然として単純であり、フローの調査やシンプルな HTTP メッセージモニター でデバッグすることができます。

ドキュメントのタグと貢献者

このページの貢献者: mfuji09, yyss
最終更新者: mfuji09,