blob: 32bd6b9800dc14453afd53134fa14b056429d8a2 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
---
title: HTTP の概要
slug: Web/HTTP/Overview
tags:
- HTML
- HTTP
- Overview
- WebMechanics
- 概要
translation_of: Web/HTTP/Overview
---
<div>{{HTTPSidebar}}</div>
<p class="summary"><span class="seoSummary"><strong>HTTP</strong> は、</span> HTML 文書などのリソースを取り出すことを可能にする{{Glossary("protocol", "プロトコル")}}です。これは<span class="seoSummary">ウェブにおけるデータ交換の基礎をなし、クライアントサーバープロトコルであり、リクエストは受け取り者 (一般にはウェブブラウザー) が生成します。文書全体は、テキスト、レイアウトの定義、画像、動画、スクリプトなど、取り込まれたさまざまなサブ文書から再構成されます。</span></p>
<p><img alt="ウェブの文書は複数のリソースの組み合わせ" src="https://mdn.mozillademos.org/files/13677/Fetching_a_page.png" style="height: 319px; width: 545px;"></p>
<p>クライアントとサーバーは、 (データの流れとは対照的に) 個々のメッセージを交換することによって通信します。クライアント (通常はウェブブラウザー) が送信するメッセージは<em>リクエスト</em>と呼ばれます。また、サーバーが回答として送信するメッセージは<em>レスポンス</em>と呼ばれます。</p>
<p><img alt="HTTP はアプリケーション層のプロトコルであり、 TCP (トランスポート層) や IP (ネットワーク層) やプレゼンテーション層以下の上の階層に当たります。" src="https://mdn.mozillademos.org/files/13673/HTTP%20&%20layers.png" style="float: left; height: 299px; padding-bottom: 15px; padding-right: 20px; width: 418px;">1990 年代初頭に設計された HTTP は、時間をかけて進化した拡張可能なプロトコルです。 HTTP は、 {{Glossary("TCP")}} または {{Glossary("TLS")}} (暗号化された TCP 接続) を使用して送信されるアプリケーション層のプロトコルですが、理論上は信頼性のある任意のトランスポート層プロトコルを使用できます。HTTP は拡張性があるため、ハイパーテキスト文書だけでなく画像や動画の取り込みや、 HTML フォームの入力結果などをクライアントからサーバーへ送信することもできます。また、リクエストに応じてウェブページを更新するために、文書の一部を取り込むこともできます。</p>
<h2 id="Components_of_HTTP-based_systems" name="Components_of_HTTP-based_systems">HTTP ベースシステムの構成要素</h2>
<p>HTTP はクライアントサーバープロトコルであり、リクエストはユーザーエージェント (または代理のプロキシ) というひとつの実体から送信されます。ほとんどの場合、ユーザーエージェントはウェブブラウザーですが、例えば検索エンジンのインデックスを収集および保守するためにウェブをクロールするロボットなど、どれでもクライアントになることができます。</p>
<p>個々のリクエストはサーバーに送信され、処理した後に<em>レスポンス</em>と呼ばれる回答を提供します。クライアントとサーバーとの間には、例えばゲートウェイや{{Glossary("Cache", "キャッシュ")}}などの様々な操作を行う、まとめて{{Glossary("Proxy_server", "プロキシサーバー")}}と呼ばれるいくつもの実体が存在しています。</p>
<p><img alt="クライアントとサーバーの連鎖" src="https://mdn.mozillademos.org/files/13679/Client-server-chain.png"></p>
<p>実際はブラウザーとサーバーの間に、ルーターやモデムなどリクエストを扱うコンピューターがさらに存在します。ウェブが階層構造で設計されたおかげで、これらはネットワークやトランスポート層の中に隠されています。 HTTP はアプリケーション層の最上位に存在します。ネットワークの問題を診断することは重要ですが、 HTTP を説明する際に下層のことはほとんど重要ではありません。</p>
<h3 id="Client_the_user-agent" name="Client_the_user-agent">クライアント: ユーザーエージェント</h3>
<p><em>ユーザーエージェント</em>は、ユーザのために働くツールです。この役割は主に、ウェブブラウザーが担います。他にも、エンジニアやウェブ開発者がアプリケーションをデバッグするために使用するプログラムである可能性もあります。</p>
<p>ブラウザーは<strong>常に</strong>、リクエストを生成する実体です。サーバーにはなりません (もっとも、サーバーが生成するメッセージをシミュレートする仕組みが近年追加されましたが)。</p>
<p>ウェブページを提供するため、ブラウザーはページを表す HTML 文書を読み込むための最初のリクエストを送信します。このファイルを解析して、実行するスクリプト、表示するレイアウトの情報 (CSS)、ページに含まれるサブリソース (通常、画像や動画) に対応する追加のリクエストを発行します。そして、ウェブブラウザーはこれらのリソースを混ぜ合わせて、完全な文書であるウェブページをユーザーに提供します。ブラウザーによって実行されるスクリプトが後の段階でさらにリソースを取り込んで、それに応じてブラウザーがウェブページを更新することがあります。</p>
<p>ウェブページは、ハイパーテキスト文書です。これは表示されているテキストの一部が新たなウェブページの取り込みを (通常、マウスのクリックによって) 発生させるリンクであり、ユーザーがユーザーエージェントを導いてウェブ内を移動できるということです。ブラウザーはこれらの導きを HTTP リクエストに変換して、さらにユーザーへ明確なレスポンスを返すために HTTP レスポンスを解釈します。</p>
<h3 id="The_Web_server" name="The_Web_server">ウェブサーバー</h3>
<p>通信路の反対側は、クライアントのリクエストに応じて文書を<em>提供する</em>サーバーがいます。サーバーは、仮想的には 1 台だけのマシンとして見えます。これは、実際は複数のサーバーの集合体であるかもしれないためであり、これらは負荷 (負荷分散)、あるいは他のコンピューター (キャッシュ、データベースサーバー、電子商取引サーバーなど) に問い合わせを行う複雑なひとまとまりのソフトウェアを分け合って、リクエストに応じて全面的または部分的に文書を生成しています。</p>
<p>サーバーは 1 台のマシンである必要性はありませんが、複数のサーバーのソフトウェアインスタンスを同じマシンで運用することができます。 HTTP/1.1 と {{HTTPHeader("Host")}} ヘッダーによって、同じ IP アドレスを共有できます。</p>
<h3 id="Proxies" name="Proxies">プロキシ</h3>
<p>ウェブブラウザーとウェブサーバーの間では、多数のコンピューターや端末が HTTP メッセージを中継します。ウェブスタックは階層構造であるため、これらの処理のほとんどはトランスポート層、ネットワーク層、物理層のいずれかで行われ、 HTTP 層から見れば透過的であり、パフォーマンスにかなりの影響を与えます。アプリケーション層で行われる処理は、通常<strong>プロキシ</strong>と呼ばれます。これらは透過的である場合、すなわち受信したリクエストをいかなる場合も変更せずに転送する場合と、透過的ではない場合、すなわちサーバーを通過する前に何らかの形でリクエストを変更する場合とがあります。プロキシはさまざまな機能を実行することがあります。</p>
<ul>
<li>キャッシュ (キャッシュは共用、あるいはブラウザーキャッシュのように個人用にできます)</li>
<li>フィルタリング (アンチウィルススキャンやペアレンタルコントロールなど)</li>
<li>負荷分散 (複数のサーバーが別々のリクエストに対応できるようにする)</li>
<li>認証 (さまざまなリソースへのアクセスを制御する)</li>
<li>ログ記録 (履歴情報の保管を可能にする)</li>
</ul>
<h2 id="Basic_aspects_of_HTTP" name="Basic_aspects_of_HTTP">HTTP の基本方針</h2>
<h3 id="HTTP_is_simple" name="HTTP_is_simple">HTTP はシンプル</h3>
<p>HTTP/2 で HTTP メッセージをフレームにカプセル化することにより複雑さが増しましたが、 HTTP は全体的にシンプルで人間が読めるように設計されています。 HTTP メッセージは人間が読んで理解することができ、開発者によるテストを容易にしています。また、初心者に対する複雑さも軽減します。</p>
<h3 id="HTTP_is_extensible" name="HTTP_is_extensible">HTTP は拡張可能</h3>
<p>HTTP/1.0 で導入された <a href="/ja/docs/Web/HTTP/Headers">HTTP ヘッダー</a>によって、プロトコルの拡張や実験が容易になっています。新しい機能であっても、クライアントとサーバーが新たなヘッダーの意味について単純な合意があれば導入できます。</p>
<h3 id="HTTP_はステートレスであるがセッションレスではない">HTTP はステートレスであるがセッションレスではない</h3>
<p>HTTP はステートレスです。同じコネクション上であっても、連続的に実行される 2 つのリクエスト間に関係性はありません。これは電子商取引のショッピングバスケットなどのように、ユーザーが一貫した方法で特定のページと対話したいときに直接問題になります。しかし HTTP の核心がステートレスであっても、 HTTP Cookie によってステートフルなセッションを実現できます。ヘッダーの拡張性を利用して、ワークフローに HTTP Cookie が追加されれば、それぞれの HTTP リクエストが同じ状況や同じ状態を共有するためにセッションを作成できるようになります。</p>
<h3 id="HTTP_and_connections" name="HTTP_and_connections">HTTP とコネクション</h3>
<p>コネクションはトランスポート層で制御されますので、 HTTP の範囲から根本的に外れています。 HTTP は下層のプロトコルがコネクションベースであることに依存はせず、<em>信頼性がある</em>、つまりメッセージを失わないこと (少なくともエラーを表示すること) だけをリクエストします。インターネットでもっとも一般的な 2 つのトランスポートプロトコルでは、 TCP には信頼性があり、 UDP には信頼性がありません。したがって HTTP は、コネクションベースである TCP 標準に依存しています。</p>
<p>クライアントとサーバーが HTTP のリクエスト/レスポンスのペアを交換する前に TCP コネクションの確立が必要で、これは複数のやり取りを必要とします。 HTTP/1.0 の既定の動作は、それぞれのリクエスト/レスポンスのペアに対して個別に TCP コネクションを開くものです。これは、複数のリクエストが近く連続して送信されたときに単一の TCP コネクションを共有することよりも非効率です。</p>
<p>この欠点を軽減するため、 HTTP/1.1 で<em>パイプライン</em> (実装が難しいことが立証されました) や<em>持続的接続</em>を導入しました。 {{HTTPHeader("Connection")}} ヘッダーを使用して、下層の TCP コネクションを部分的に制御できます。 HTTP/2 はひとつのコネクションで複数のメッセージを多重化するように進化しました。コネクションををウォーム状態に保つのに役立ち、効率が向上します。</p>
<p>より HTTP に適したトランスポートプロトコルを設計する実験が進んでいます。たとえば Google は、より信頼性があり効率的なトランスポート層プロトコルを提供するため、 UDP 上に構築する <a href="https://ja.wikipedia.org/wiki/QUIC">QUIC</a> の実験を行っています。</p>
<h2 id="What_can_be_controlled_by_HTTP" name="What_can_be_controlled_by_HTTP">HTTP が制御できること</h2>
<p>HTTP の拡張性により時間をかけて、ウェブの制御性や機能性が向上できました。キャッシュや認証の方法は、 HTTP の草創期から取り扱われてきた機能です。対照的に、<em>オリジン制約</em>を緩和する機能は2010年代にようやく追加されました。</p>
<p>HTTP で制御できる一般的な機能は以下のとおりです。</p>
<ul>
<li><em><a href="/ja/docs/Web/HTTP/Caching">キャッシュ</a></em><br>
文書をどのようにキャッシュするかを、 HTTP で制御できます。サーバーはプロキシやクライアントに対して、何をどれだけの間キャッシュするかを指示できます。クライアントは中間のキャッシュプロキシに対して、保存されている文書を無視するよう指示できます。</li>
<li><em>オリジン制約の緩和</em><br>
のぞき見や他のプライバシー侵害を避けるため、ウェブブラウザーはウェブサイト間を厳密に分割するよう強制しています。<strong>同一オリジン</strong>のページだけが、ウェブページの情報すべてにアクセスできます。この制約はサーバーにとって負担になりますが、 HTTP ヘッダーでサーバー側の厳密な分割を緩和できます。これにより、さまざまなドメインを情報源とした情報の寄せ集めの文書を作成できます。ただし、このようにするセキュリティ上の理由があります。</li>
<li><em>認証</em><br>
特定のユーザーしかアクセスできないように保護されたページがあるでしょう。基本的な認証は HTTP が提供しており、 {{HTTPHeader("WWW-Authenticate")}} などのヘッダーを使用するか、 <a href="/ja/docs/Web/HTTP/Cookies">HTTP Cookie</a> を使用した特別なセッションを設定するかします。</li>
<li><em><a href="/ja/docs/Web/HTTP/Proxy_servers_and_tunneling">プロキシとトネリング</a></em><br>
サーバーやクライアントがイントラネット内に配置されて、他のコンピューターから本当の IP アドレスが見えなくなっていることがよくあります。このネットワーク境界を渡るため、 HTTP リクエストはプロキシを通過します。すべてのプロキシが HTTP プロキシであるとは限りません。たとえば、 SOCKS プロトコルはより低い層で動作します。ほかにも FTP などがそれらのプロキシで処理されることがあります。</li>
<li><em>セッション</em><br>
HTTP Cookie を使用して、リクエストとサーバーのセッションを関連付けできます。これにより HTTP がステートレスプロトコルであるにもかかわらず、セッションを作成できます。これは電子商取引のショッピングバスケットだけでなく、出力内容にユーザー設定を適用できるサイトでも有用です。</li>
</ul>
<h2 id="HTTP_flow" name="HTTP_flow">HTTP のフロー</h2>
<p>クライアントがサーバー (最終目的地のサーバーまたは中間のプロキシ) と通信したいとき、クライアントは以下の段階を踏みます。</p>
<ol>
<li>TCP コネクションを開く: TCP コネクションはひとつまたは複数のリクエストを送信したり、回答を受け取ったりするために使用します。クライアントは新しいコネクションを開く、既存のコネクションを再使用する、あるいはサーバーに対して複数の TCP コネクションを開くことができます。</li>
<li>HTTP メッセージを送信する: HTTP メッセージを (HTTP/2 より前) は人間が読むことができます。 HTTP/2 では単純なメッセージがフレーム内にカプセル化されており、直接読むことが不可能になりましたが、原理は変わっていません。
<pre class="line-numbers language-html"><code class="language-html">GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr</code></pre>
</li>
<li>サーバーから送信されたレスポンスを読み取る:
<pre class="line-numbers language-html"><code class="language-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
<!DOCTYPE html... (ここに、リクエストした 29769 バイトのウェブページがある)</code></pre>
</li>
<li>次のリクエストのために、コネクションを閉じるか再使用する</li>
</ol>
<p>HTTP パイプラインが有効である場合は、最初のレスポンスが完全に返るのを待たずに複数のリクエストを送信できます。 HTTP パイプラインは既存のネットワークで実装するのが難しいことが立証されており、古いソフトウェアと最新バージョンのソフトウェアが共存しています。 HTTP パイプラインは、 HTTP/2 でフレーム内にリクエストを強力に多重化する機能によって置き換えられました。</p>
<h2 id="HTTP_Messages" name="HTTP_Messages">HTTP メッセージ</h2>
<p>HTTP/1.1 以前の HTTP メッセージは、人間が読むことができます。 HTTP/2 ではこれらのメッセージがバイナリ構造の<em>フレーム</em>に埋め込まれており、ヘッダーの圧縮や多重化といった最適化が可能になりました。本来の HTTP メッセージの部分だけがこのバージョンの HTTP で送信されていても、各メッセージの意味は変わっておらず、クライアントは本来の HTTP/1.1 メッセージを (事実上) 再構成します。したがって、 HTTP/2 メッセージを HTTP/1.1 形式で理解することは役に立ちます。</p>
<p>HTTP メッセージはリクエストとレスポンスの 2 種類あり、それぞれ固有の形式になっています。</p>
<h3 id="Requests" name="Requests">リクエスト</h3>
<p>HTTP リクエストの例です。</p>
<p><img alt="基本的な HTTP リクエスト" src="https://mdn.mozillademos.org/files/13687/HTTP_Request.png" style="height: 336px; width: 693px;"></p>
<p>リクエストは以下の要素で構成されます。</p>
<ul>
<li>HTTP <a href="/ja/docs/Web/HTTP/Methods">メソッド</a>。通常、クライアントが実行したい操作を定義する {{HTTPMethod("GET")}} や {{HTTPMethod("POST")}} のような動詞か、{{HTTPMethod("OPTIONS")}} や {{HTTPMethod("HEAD")}} のような名詞です。一般的にクライアントはリソースを取り込む (<code>GET</code> を使用) か <a href="/ja/docs/Web/Guide/HTML/Forms">HTML フォーム</a> の値を送信する (<code>POST</code> を使用) ことを望みますが、場合によってはほかの操作が必要になります。</li>
<li>取り込むリソースのパス。状況から明らかであればリソースの URL はこの要素から取り除かれます。たとえば{{Glossary("protocol","プロトコル")}} (<code>http://</code>)、{{Glossary("domain","ドメイン")}} (ここでは <code>developer.mozilla.org</code>)、TCP {{Glossary("port","ポート")}} (ここでは <code>80</code>) が取り除かれます。</li>
<li>HTTP プロトコルのバージョン。</li>
<li>サーバーに追加の情報を与える任意の <a href="/ja/docs/Web/HTTP/Headers">ヘッダー</a>。</li>
<li><code>POST</code> のようなメソッドではレスポンスと同様に、送信するリソースを包含したボディがあります。</li>
</ul>
<h3 id="Responses" name="Responses">レスポンス</h3>
<p>レスポンスの例です。</p>
<p><img alt="" src="https://mdn.mozillademos.org/files/13691/HTTP_Response.png" style="height: 494px; width: 758px;"></p>
<p>レスポンスは以下の要素で構成されます。</p>
<ul>
<li>準拠する HTTP プロトコルのバージョン。</li>
<li><a href="/ja/docs/Web/HTTP/Status">ステータスコード</a>。リクエストが成功したか否か、およびその理由を示します。</li>
<li>ステータスメッセージ。ステータスコードの簡単な説明ですが、権威はありません。</li>
<li>リクエストと同様の HTTP <a href="/ja/docs/Web/HTTP/Headers">ヘッダー</a>。</li>
<li>(省略可) リソースを含む本文。</li>
</ul>
<h2 id="APIs_based_on_HTTP" name="APIs_based_on_HTTP">HTTP に基づく API</h2>
<p>最もよく使われている HTTP に基づく API は {{domxref("XMLHttpRequest")}} API で、{{Glossary("user agent", "ユーザーエージェント")}}とサーバーの間でデータを交換するために使用することができます。新しい {{domxref("Fetch API")}} は、同じ機能をより強力で柔軟な一連の機能で提供します。</p>
<p>他の API、 <a href="/ja/docs/Web/API/Server-sent_events">server-sent event</a> は、サーバーがクライアントにイベントを送信することができる一方通行のサービスで、 HTTP をトランスポートの仕組みとして利用しています。クライアントのブラウザーは HTTP ストリームに届くメッセージを自動的に適切な {{domxref("Event")}} オブジェクトに変換し、もしイベントの{{domxref("Event.type", "型")}}が分かればその型に登録されているイベントハンドラーに配信し、型に対してイベントハンドラーが設定されていない場合は、 {{domxref("EventSource.onmessage", "onmessage")}} イベントハンドラーに配信します。</p>
<h2 id="Conclusion" name="Conclusion">まとめ</h2>
<p>HTTP は容易に使用できる、拡張可能なプロトコルです。クライアントサーバー構造と単純にヘッダーを追加できる機能性を組み合わせて、 HTTP はウェブの機能拡張に合わせて進化できます。</p>
<p>HTTP/2 でパフォーマンスを向上するため、フレーム内に HTTP メッセージを埋め込むことにより複雑さがいくらか増しましたが、メッセージの基本的な構造は HTTP/1.0 から同じままです。セッションのフローは依然として単純であり、フローの調査やシンプルな <a href="/ja/docs/Tools/Network_Monitor">HTTP メッセージモニター</a>でデバッグすることができます。</p>
|