52. An overview of HTTP
【所要時間】
3時間40分(2018年9月19日)
【概要】
HTTPサーバーについて
【要約・学んだこと】
HTTPはHTMLドキュメントなどのリソースを取り出すことができるプロトコルだ。これはウェブ上のデータ交換の基礎となり、クライアントサーバープロトコルは、リクエストが受け取り者(通常はウェブサーバー)によって開始される。完成されたドキュメントは、例えばテキスト、レイアウト、画像、ビデオなど取り出されたことなるサブドキュメントによって再構築される。
クライアントやサーバーは個々のメッセージ(データの流れとは対照的に)の交換によって通信する。クライアントによって送られたメッセージ、(通常はウェブブラウザー)はリクエストと呼ばれ、答えとしてサーバーに送られたメッセージはレスポンスと呼ばれる。
HTTPは拡張可能なプロトコルだ。HTTPは TCPまたはTLS-encrypted TCP(暗号化されたTCP接続)を使用して送信されるアプリケーションレイヤープロトコルだが、理論上信頼できる任意のトランスポートプロトコルが使われる。
拡張性があるため、hypertextドキュメントの取り込みだけでなく、画像、ビデオ、HTMLフォームの結果のような、サーバーへコンテンツを送信することもできる。HTTPは要求によってWebページを更新するためにドキュメントの一部を取り込むことも可能。
Components of HTTP-based systems
HTTPはクライアントサーバープロトコルだ。リクエストはユーザーエージェント(または代理のプロキシ)という1つの実体から送られる。ほとんどの場合はユーザーエージェントはWebブラウザだが、何にでもなれる。例えばサーチエンジンのインデックスの収集と保守のためにウェブをクロールするロボットなどだ。
個々の要求はサーバーに送られ、それを処理し、応答とよばれる答えを提供する。このリクエストと応答の間には、ゲートやcachesとしての操作など様々なことを行う複数の実体が存在している。これらをまとめて proxiesと呼ぶ。
実際は、ブラウザとサーバーの間にはよりたくさんのコンピュータが存在し、リクエストを処理する。ルーターやモデムなどだ。ウェブがレイヤーデザインのため、これらはネットワークやトランスポートレイヤーの中に隠される。
HTTPはアプリケーションレイヤーのトップに位置する。ネットワークプロブレムの診断は重要だが、HTTPの説明に、下のレイヤーはほとんど関係ない。
Client: the user-agent
ユーザーエージェントはユーザーのために働く任意のツールの事。この役割は主にウェブブラウザによって行われる。エンジニアやウェブディベロッパーがアプリのデバッグに使われるプログラムのような例外もある。
ブラウザは常にリクエストを作る実体であり、サーバーではない。(メカニズムによってはサーバーが作るメッセージをシミュレートするものが近年追加された。)
Webページを表現するために、ブラウザはページからHTMLドキュメントを読み込むために最初のリクエストを送る。このファイルを解析し、実行するスクリプト、表示するためのレイアウト情報(CSS)、ページに含まれるサブリソース(通常画像やビデオ)に対して、追加のリクエストを送る。
Webブラウザはこれらのリソースを混ぜ合わせ、ユーザーに完全なドキュメント、Webページを提供する。
ブラウザに実行されたスクリプトは、のちのフェーズでよりたくさんのリソースを読み込み、ブラウザはそれに伴いWebページを更新する。
Webページはhypertext documentだ。これは表示されたテキストの一部が、新たなWebページを読み込むためにアクティベートされた(通常マウスによってクリックされた)リンクであり、ユーザーがユーザーエージェントに命令し、ウェブ内を移動できる。
ブラウザはこれらのHTTPリクエストの要求を変換して、明確なレスポンスをユーザーに提供するため、HTTPレスポンスをさらに解釈する。
The Web server
通信チャネルの反対側には、クライアントによるリクエストに応じてドキュメントを提供するサーバーがある。サーバーは実質的に1台のマシーンとして見える。なぜなら実際は複数のサーバーかもしれず、負荷(負荷分散)、他のコンピュータ(キャッシュ、データベースサーバー、eコマースサーバーなど)に質問する複雑なソフトウェアをシェアし、要求に応じて全体的、部分的にドキュメントを作る。
サーバーは1台のマシーンである必要はないが、複数のサーバーを同じマシンで使うことができる。HTTP/1.1と、 Host
ヘッダーで、同じIPアドレスを共有できる。
Proxies
Webブラウザとサーバーの間では、多数のコンピュータとマシンがHTTPメッセージを中継する。ウェブスタックは階層構造のため、これらの処理のほとんどはトランスポート、ネットワーク、物理レベルのどこかで行われ、HTTPレイヤーは透明になり、パフォーマンスに大きな影響を与える。アプリケーションレイヤーで行われる処理は、一般的にプロキシと呼ばれる。これらが透明であってもなくても(プロキシ通過でリクエストを変更する)、たくさんの機能を実行する。
- キャッシング(キャッシュはブラウザキャッシュのように共用にもプライベートにもなりうる)
- フィルタリング(ウィルススキャン、ペアレンタルコントロールなど)
- 負荷分散(複数のサーバーが異なるリクエストに対応できる)
- 認証(異なるリソースへのアクセスを制御する)
- ロギング(履歴情報の保管を許可する)
Basic aspects of HTTP
HTTP/2がHTTPメッセージをフレームにカプセル化することでより複雑になったが、HTTPは一般的にシンプルで、人間が読めるように設計されている。そのため、ディベロッパーテストを簡単にし、初心者への複雑さも減らしている。
HTTP is extensible
HTTP/1.0で導入された HTTP headersが、プロトコルの拡張や実験を簡単にした。新機能はクライアントとサーバーが新しいヘッダーの意味に簡単な合意があれば導入かのう。
HTTP is stateless, but not sessionless
HTTPはステートレスだ。同じコネクション上で連続して実行される2つのリクエストの間に、繋がりはない。これはユーザーが一貫した方法で特定のページと対話したいときに問題になりうる。例えば、eコマースバスケットを使う時などだ。しかし、HTTP自身のコアがステートレスでも、HTTPクッキーによって、ステートフルなセッションが使える。
ヘッダーの拡張性を使い、HTTPクッキーはワークフローに加えられることができる。それぞれのHTTPリクエストが同じコンテクストやstateを共有するためにセッションをつくることで可能になる。
HTTP and connections
コネクションはトランスポートレイヤーで制御されているため、根本的にHTTPの範囲外だ。HTTPは下層のトランスポートプロトコルがコネクションベースであることは要求しない。信頼性だけを要求する。またはメッセージを失わないことだけを要求する。(エラーを少なくとも表示する)
インターネット上の2つの最も一般的なトランスポートプロトコル間では、TCPは信頼でき、UDPはそうでない。HTTPはTCPスタンダードに依存する。これはコネクションベースで、コネクションが常に必要でないとしてもだ。
HTTP1.0はリクエスト、レスポンスの交換するごとに、TCPコネクションを開くことが、2つの大きな欠点となっている。コネクションを開くことが、いくつかのメッセージのやりとりを必要とすると前、遅い。しかし、複数のメッセージが送られ、定期的的に送られるたびに効果的になってくる。ウォームコネクションはコールドコネクションより効率的だ。
この欠点を軽減するため、HTTP/1.1はパイプライン(実装が難しいことが証明された)と不断コネクションを導入した。下層のTCPコネクションは部分的にConnection
ヘッダーを使用してコントロールされる。HTTP/2は複数のメッセージを1つのコネクションで多重化できるように大きく進化し、ウォームコネクションの維持や、さらなる効率性に役立つ。
HTTPにより適したトランスポートプロトコルの設計は進んでいる。例えば、Googleは QUIC という、より信頼でき、効率的にトランスポートプロトコルを提供するためにUDP上で構築で構築されるものの実験をしている。
What can be controlled by HTTP
HTTPの拡張性のおかげで、時間をかけ、ウェブの制御や機能が向上した。キャッシュや認証メソッドはHTTPの初期から扱われてきた機能だ。一方、オリジンコントラストを緩和する機能は2010年代にようやく追加された。
HTTPで一般的に制御できる機能はこれらだ。
- キャッシュ
ドキュメントがキャッシュされる方法をHTTPで制御できる。サーバーはプロキシ、クライアント、なんのキャッシュをどれくらいの間キャッシュするかを支持できる。クライアントは中間のキャッシュプロキシに、保存されているドキュメントを無視するように指示できる。 - オリジンコントラストの制約
覗き見やプライバシーの侵害を防ぐため、Webブラウザはウェブサイトとの厳格な分割を強制している。同じオリジンからのページだけがWebページの全ての情報にアクセスできる。サーバーにはこの制約は重荷だが、HTTPヘッダーはこのサーバーサイドの厳格な分離を緩和でき、様々なドメインをソースとした情報を寄せ集めてドキュメントを作れる。(こうするためのセキュリティ上の理由がある) - 認証
特定のユーザーのみがアクセスできるように保護されたページもあるだろう。基本的な認証はHTTPに提供されていて、WWW-Authenticate
か似たようなヘッダーを使うか、 HTTP cookies を使い特定のセッションを設定する。 - プロキシとトンネリング
サーバーやクライアントがしばしばイントラネットに位置し、本当のIPガ他人に見えなくなることがある。HTTPはこのネットワーク境界を渡るために、プロキシを通過する。全てのプロキシがHTTPプロキシとは限らない。例えば、SOCKSプロトコルは低いレベルで動作する。他にはftpなどがこれらのプロキシで処理される。 - セッション
HTTPクッキーを使用することでサーバーのstateと繋がることができる。HTTPがステートレスプロトコルであるが、これはセッションを作る。これはeコマースショッピングのバスケットだけでなく、出力内容にユーザー設定を適用できるサイトでも有益だ。
HTTP flow
クライアントがサーバーと通信したい時(最終のサーバーでも中間のプロキシでも)下記のステップで進む。
- TCPコネクションを開く。
TCPコネクションはリクエストを1つ、もしくは複数送るのに使われる、回答を受け取る。クライアントは新しいコネクションを開くことができ、既存のコネクションを拒否すること、サーバーに複数のTCPコネクションを開くことができる。 - 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... (here comes the 29769 bytes of the requested web page)
4. さらなる要求のためにコネクションを閉じるか、再び使う。
もしHTTP パイプライニングがアクティブなら、いくつかのリクエストは最初のレスポンスが完全に受信するのを待つことなく送られることができる。HTTPパイプライニングは既存のネットワークでは実装が難しいと証明されていて、古いソフトウェアと新しいバージョンのソフトウェアがある。HTTPパイプラインニングは、HTTP/2でフレーム内により強力に多重化するリクエストと置き換えられた。
HTTP Messages
HTTP/1.1以前のHTTPメッセージは人間が読める。HTTP/2では、これらのメッセージは新しいバイナリ構造、フレームに埋め込まれていて、ヘッダーの圧縮や、多重化のような最適化ができるようになった。たとえオリジナルのHTTPメッセージの一部だけがこのバージョンのHTTPで送信されたとしても、それぞれのメッセージの意味は変わらず、クライアントはオリジナルのHTTP/1.1リクエストを再構築(事実上)する。それゆえ、HTTP/1.1フォーマットで、HTTP/2メッセージを理解することは有益だ。
HTTPメッセージはリクエストと応答の二種類があり、それぞれ自身のフォーマットになっている。
Requests
HTTP リクエストの例:
GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr
GET:
Method
/:
Path
HTTP/1.1:
プロトコルのバージョン
Host: developer.mozilla.org
Accept-Language: fr
ヘッダー
リクエストは下記の要素で構成される。
- HTTPメソッド。通常、クライアントが実行したい操作を
GET
,POST
といった動詞、もしくはOPTIONS
orHEAD
といった名詞で定義する。一般的に、クライアントはリソースを読み込む(GETを使う)か、 HTML form のvalueを送信する(POSTを使う)ことを臨が、他の場合では他の操作が必要になる。 - 取り込むリソースのパス。リソースのURLはコンテキストから明らかなので、要素から取り除かれる。例えば、プロトコル(http://)、ドメイン(developer.mozilla.org)、TCPポート(80)がここでは取り除かれる。
- HTTPプロトコルのバージョン
- サーバーに追加情報を与える任意のheaders
- POSTのようなメソッドでは、応答同様に送られるリソースを含むbodyがある。
Responses
応答の例:
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
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
ヘッダー
レスポンスは下記の要素で構成される。
- 準拠するHTTPプロトコルのバージョン
- status code リクエストが成功したかしてないか、なぜなのかを表示する。
- ステータスメッセージ。ステータスコードの権威のない簡単な説明
- 要求と同様なHTTP headers
- 任意の取り込んだリソースを含むbody
APIs based on HTTP
HTTPのトップに基づく最も一般的に使われるAPIは、 XMLHttpRequest
APIだ。これはuser agentとサーバー間でデータを交換するのに使うことができる。
他のAPIでは、server-sent events は、サーバーがクライアントにイベントを送ることができる一方通行のサービスで、トランスポートメカニズムとしてAPIを使う。EventSource
インターフェイスを使うことで、クライアントはコネクションを開き、イベントハンドラーを確立する。
クライアントブラウザーは自動的にHTTPストリームに届くメッセージを適切な Event
オブジェクトに変換し、もしイベントのtype
が知られていたら、登録しているイベントハンドラーにメッセージを送る。もしイベントハンドラーが特定のtypeに確立されていなければ、onmessage
を送る。
Conclusion
HTTPは簡単に使える拡張されたプロトコルだ。クライアントサーバーの構成と、単純にヘッダーを加える能力を組みあわせ、HTTPがウェブの拡張機能に合わせて進化する。
HTTP/2でパフォーマンスの向上のためにフレーム内にHTTPメッセージを埋め込むことで、複雑になったが、基本的なメッセージ構成はHTTP/1.0から変わらない。セッションフローは簡単なままで、調査や簡単な HTTP message monitorでデバッグできる。
【わからなかったこと】
よくわからないのは色々見て見たらわかりやすかったが、特にわからなかったのはHTTP/2。こちらを参照したらわかりやすかった。
【感想】
よく聞く単語が多いが、知らない内容だった。