HTTP - HTTPメッセージ

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

HTTPは、HTML文書等のリソースを取得するためのプロトコルである。
これは、Web上のあらゆるデータ交換の基礎であり、クライアントサーバプロトコルである。

つまり、リクエストは受信者(通常はWebブラウザ)によって開始される。
例えば、テキスト、レイアウト記述、画像、動画、スクリプト等、フェッチされた様々なサブドキュメントから完全なドキュメントが再構築される。

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

1990年代初頭に設計されたHTTPは、時代とともに進化してきた拡張可能なプロトコルである。
TCP、または、TLSで暗号化されたTCP接続で送信されるアプリケーション層プロトコルであるが、理論的には信頼性の高いトランスポートプロトコルであれば何でも使用できる。
その拡張性により、ハイパーテキストドキュメントだけでなく、画像や動画を取り込んだり、HTMLフォームの結果のようにコンテンツをサーバに投稿したりするのにも使用される。

また、HTTPはオンデマンドでWebページを更新するために、文書の一部をフェッチするのにも使用される。


HTTPの基本

単純な構造

HTTP/2のような、HTTPメッセージをフレームにカプセル化することにより複雑さが加わったとしても、HTTPは一般的にシンプルで人間が読めるように設計されている。

HTTPメッセージは人間が読んで理解することができ、開発者にとってはテストが容易になる。

拡張可能性

HTTP/1.0で導入されたHTTPヘッダは、このプロトコルの拡張を容易にする。

クライアントとサーバが新しいヘッダのセマンティクスについて合意するだけで、新しい機能を導入することもできる。

HTTPはステートレス、かつ、非セッションレス

HTTPはステートレス (HTTPリクエスト / HTTPレスポンスを1度送受信するごとに接続を切ることをステートレス型と呼ぶ) である。

同じコネクション上で連続して実行される2つのリクエストの間にはリンクがない。

例えば、eコマースのショッピングバスケットを使用する場合、特定のページと首尾一貫してやりとりしようとするユーザにとって問題となる見込みがある。
しかし、HTTPのコア自体はステートレスであるが、HTTPクッキーはステートフルなセッションの使用を可能にする。

ヘッダの拡張性を使用して、HTTPクッキーはワークフローに追加されて、各HTTPリクエストで同じコンテキスト、つまり、同じ状態を共有するセッション生成を可能にする。

HTTPとコネクション

コネクションはトランスポート層で制御されるため、基本的にHTTPの範囲外である。
HTTPは基礎となるトランスポートプロトコルがコネクションベースであることを要求しているわけではない。
インターネット上で最も一般的な2つのトランスポートプロトコルの内、TCPは信頼性があり、UDPは信頼性がない。
したがって、HTTPは、コネクションベースであるTCP標準に依存している。

クライアントとサーバがHTTPリクエスト / レスポンスのペアを交換する前に、TCPコネクションを確立する必要がある。
HTTP/1.0のデフォルトの動作は、HTTPリクエスト / レスポンスのペアごとに別々のTCPコネクションをオープンすることである。
これは、複数のリクエストが連続して送信される場合、1つのTCPコネクションを共有するよりも効率が悪い。

この欠陥を軽減するために、HTTP/1.1ではパイプライン化(実装が難しいことが判明)と持続的接続が導入された。
基礎となるTCP接続は、Connectionヘッダを使用して部分的に制御できる。
HTTP/2はさらに一歩進み、単一のコネクション上でメッセージを多重化することにより、コネクションをより効率的にする。

現在では、HTTPにより適したトランスポートプロトコルを設計するための実験が進行中である。
例えば、GoogleはUDPをベースに、より信頼性が高く効率的なトランスポートプロトコルを提供するQUICの実験を行っている。


HTTPで制御できること

HTTPのこの拡張可能な性質は、時代とともに、Webの制御と機能性の向上を可能にしてきた。
キャッシュや認証方法は、HTTPの歴史の初期に扱われていた機能である。
対照的に、オリジン制約を緩和する機能は、2010年代に追加された。

HTTPで制御可能な一般的な機能を、以下に示す。

  • キャッシュ
    ドキュメントをどのようにキャッシュするかは、HTTPで制御できる。
    サーバはプロキシやクライアントに、何をどれくらいの期間キャッシュするかを指示することができる。

    クライアントは中間キャッシュプロキシに、保存されたドキュメントを無視するように指示できる。
  • オリジン制約の緩和
    盗聴やその他のプライバシー侵害を防ぐため、WebブラウザはWebサイト間の厳格な分離を強制している。
    同じオリジンからのページのみが、Webページの全ての情報にアクセスできる。
    このような制約はサーバにとって負担であるが、HTTPヘッダは、サーバ側でこの厳密な分離を緩和することができ、ドキュメントが異なるドメインからの情報のパッチワークになることを可能にする。
  • 認証
    ページによっては、特定のユーザのみがアクセスできるように保護されている場合がある。
    BASIC認証は、WWW-Authenticateや同様のヘッダを使用する、または、HTTPクッキーを使用して特定のセッションを設定することにより、HTTPによって提供される場合がある。
  • プロキシとトンネリング
    サーバやクライアントは、ほとんどの場合はイントラネット上にあり、他のコンピュータから本来のIPアドレスを隠している。
    そして、HTTPリクエストは、このネットワークの障壁を越えるためにプロキシを経由する。

    また、全てのプロキシがHTTPプロキシというわけではない。
    例えば、SOCKSプロトコルは、より低いレベルで動作する。
    FTPのような他のプロトコルは、これらのプロキシで処理することができる。
  • セッション
    HTTPクッキーを使うことにより、リクエストとサーバの状態を結びつけることができる。
    基本的なHTTPは、ステートのないプロトコルであるにもかかわらず、セッションを作成する。
    これは、eコマースのショッピングのみでなく、ユーザによる出力の設定を可能にするあらゆるサイトに役立つ。



HTTPの流れ

クライアントがサーバ (最終サーバ、または、中間プロキシ) と通信する場合、以下のような手順で実行される。

  1. TCPコネクションを開く。
    TCPコネクションは、リクエストを送信して、その回答 (レスポンス) を受信するために使用される。
    クライアントは、新しいコネクションを開いたり、既存のコネクションを再利用したり、サーバへの複数のTCPコネクションを開いたりすることができる。
  2. HTTPリクエストを送信する。
    HTTPメッセージ (HTTP/2以前) は人間が読むことができる。
    HTTP/2では、これらの単純なメッセージはフレームにカプセル化され、直接読むことは不可能であるが、原理は変化していない。

    GET / HTTP/1.1
    Host: developer.mozilla.org
    Accept-Language: fr

  3. WebサーバがHTTPリクエストに対応する処理を行う。

  4. Webサーバから送信されたレスポンスを読む。
    クライアント端末は、取得したhtmlファイルを確認して、CSSや画像ファイルが必要な場合は再度Webサーバにリクエストを送信する。

    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 come the 29769 bytes of the requested web page)

  5. 接続を閉じる、または、次のリクエストのために再利用する。


HTTP Connection 1.png


HTTPパイプラインを有効にする時、最初のレスポンスが完全に受信されるのを待たずに、複数のリクエストを送信することができる。
HTTPパイプラインは、古いソフトウェアが最新バージョンと共存している既存のネットワークでは実装が難しいことが判明している。

HTTPパイプラインは、HTTP/2において、フレーム内でリクエストを多重化する、より堅牢なものに取って代わった。


HTTPメッセージ

HTTP/1.1以前で定義されたHTTPメッセージは、人間が読むことができる。
HTTP/2では、これらのメッセージはフレームというバイナリ構造に埋め込まれ、ヘッダの圧縮や多重化などの最適化が可能になる。

元のHTTPメッセージの一部のみがHTTP/2で送信されたとしても、各メッセージのセマンティクスは変更されず、クライアントは元のHTTP/1.1リクエストを (仮想的に) 再構成する。
したがって、HTTP/1.1形式でHTTP/2メッセージを理解することは有用である。

HTTPメッセージには、HTTPリクエストとHTTPレスポンスの2種類があり、それぞれ独自の書式をもつ。

HTTPリクエストの構成

HTTPリクエストは、以下の要素で構成される。

POST /submit HTTP/1.1              # リクエスト行
Host: example.com                  # ヘッダフィールド
Content-Type: application/json     # ヘッダフィールド
Content-Length: 38                 # ヘッダフィールド
                                   # 空行
{"username": "john", "age": 30}    # メッセージボディ


HTTP Request 1.png
図. HTTPリクエスト


リクエスト行

メソッド、URI、HTTPバージョンを含む。

  • HTTPメソッド
    GET、POST、DELETE、OPTIONS、HEADがあり、クライアントが実行する操作を定義する。
    例えば、クライアントがリソースをフェッチする場合 (GET)、または、HTMLフォームの値をポストする場合 (POST) 等がある。
  • フェッチするリソースのパス
    コンテキストからプロトコル (http://)、ドメイン (developer.mozilla.org)、TCPポート番号 (80番等) を取り除いたリソースのURLである。
  • HTTPプロトコルのバージョン


# 例
GET /index.html HTTP/1.1


ヘッダフィールド

リクエストの追加情報を含む。

  • サーバに追加情報を伝えるオプションのヘッダ
  • POSTのようないくつかのメソッドでは、送信されたリソースを含むレスポンスと似たボディ


# 例
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html


空行

単純な改行であるが、ヘッダフィールドとメッセージボディを区切る重要な要素である。

メッセージボディ

主に、POSTリクエスト等でデータを送信する時にパラメータが記述される。
GETリクエストの場合は、空になることが多い。

# 例 (POSTパラメータ)
{"username": "john", "age": 30}


HTTPレスポンスの構成

HTTPレスポンスは4つの主要な部分から構成されており、各部分が明確な役割を持つ。

特にヘッダフィールドは、クライアントがレスポンスを適切に処理するための重要な情報を提供する。

# HTTPレスポンスの例

HTTP/1.1 200 OK                         # ステータス行
Date: Thu, 14 Nov 2024 12:00:00 GMT     # ヘッダフィールド
Server: Apache/2.4.41 (Unix)            # ヘッダフィールド
Content-Type: text/html; charset=UTF-8  # ヘッダフィールド
Content-Length: 138                     # ヘッダフィールド
                                        # 空行
<!DOCTYPE html>                         # ボディ
 <html>
   <head>
     <title>Example Page</title>
   </head>
   <body>
     <h1>Hello, World!</h1>
   </body>
 </html>


HTTP Response 1.png
図. HTTPレスポンス


ステータス行
  • HTTPプロトコルのバージョン
  • ステータスコード (HTTPリクエストが成功の可否、および、その理由が記載)
  • ステータスメッセージ、ステータスコードの非正規の短い説明


下表に、主なHTTPレスポンスのステータスコードの一覧を示す。

  • 1xx
    情報
  • 2xx
    正常 (成功)
  • 3xx
    リダイレクト関連
  • 4xx
    クライアント側のエラー
  • 5xx
    サーバ側のエラー


HTTPレスポンスのステータスコード
ステータスコード 説明
200 OK
リクエストが成功して、レスポンスが返されたことを示す。
301 Moved Parmanently
指定したリソースは移動したため、新しい場所から取得することを示す。
例えば、Webサイトが恒久的に移転した場合は、この値を設定する。
302 Moved Temporarily
指定したリソースは移動したため、新しい場所から取得することを示す。
例えば、Webサイトが一時的に移転した場合は、この値を設定する。
304 Not Modified
指定したファイルは変更されていないため、Webブラウザのキャッシュを表示する。
401 Unauthorixed
認証に失敗したことを示す。
403 Forbidden
アクセス権限が無いことを示す。
404 Not Found
リクエストしたアドレスのページが存在しないことを示す。
500 Internal Server Error
Webサーバにおいて、内部エラーが発生していることを示す。
502 Bad Gateway
ゲートウェイが無効なレスポンスを受信したことを示す。
503 Service Unavailable
サービスが提供できないことを示す。
例えば、Webサーバに負荷が掛かりすぎた場合等に表示される。
504 Gateway Timeout
上流からのレスポンスが所定時間内に得られない場合に表示される。


ヘッダフィールド

レスポンスに関する各種メタ情報がある。

  • HTTPリクエストと同様のHTTPヘッダ
  • オプションとして、取得したリソースを含むボディ


# 例
Date: Thu, 14 Nov 2024 12:00:00 GMT
Server: Apache/2.4.41 (Unix)
Content-Type: text/html; charset=UTF-8
Content-Length: 138
Cache-Control: no-cache


主要なヘッダフィールドの役割を以下に示す。

  • Content-Type
    メッセージボディのデータ形式を指定
  • Content-Length
    メッセージボディのサイズ (バイト)
  • Cache-Control
    キャッシュの動作を制御
  • Set-Cookie
    クライアントにCookieを設定
  • Location
    リダイレクト先のURLを指定 (3xxステータスで使用)


空行

単純な改行であるが、ヘッダフィールドとメッセージボディを区切る必須要素である。

メッセージボディ
  • レスポンスの実際のコンテンツ (HTMLファイルの内容、JSON、画像データ等)
  • Content-Typeヘッダで形式を指定する。



HTTPベースのAPI

HTTPをベースにしたAPIで最もよく使用されるものは、Fetch APIである。
これは、JavaScriptからHTTPリクエストを行うことができる。

Fetch APIは、XMLHttpRequest APIを置き換えるものである。

もう1つのAPIであるサーバ送信イベントは、HTTPをトランスポートメカニズムとして使用して、サーバがクライアントにイベントを送信できる一方向のサービスである。
EventSourceインタフェースを使用して、クライアントは接続を開き、イベントハンドラを確立する。

クライアントブラウザ (Webブラウザ) は、HTTPストリーム上に到着したメッセージを自動的に適切なEventオブジェクトに変換する。
そして、既知の場合はイベントのタイプに対して登録されているイベントハンドラに、タイプ固有のイベント・ハンドラが確立されていない場合はonmessageイベントハンドラに、それらを配信する。


POSTとPUTの違い

POST (作成・追加)

主に、新しいリソースを作成するために使用する。
クライアントはサーバにデータを送信して、サーバはそれを受信して新しいリソースを作成する。

同じデータを複数回送信しても、常に新しいリソースが作成される。

PUT (更新・置換)

既存のリソースを更新するために使用する。
クライアントはサーバに更新するリソースを送信して、サーバはそのデータで既存のリソースを置き換える。

PUTメソッドは、同じデータを複数回送信しても常に同じ結果が得られるように設計されている。

安全性

  • POST
    通常、POSTリクエストは安全ではないと見なされる。
    つまり、同じリクエストを繰り返しても同じ結果が得られない可能性がある。

  • PUT
    PUTリクエストは一般的に安全であると見なされる。
    同じPUTリクエストを複数回送信しても、常に同じ結果が得られるからである。


冪等性

  • POST
    通常、POSTは冪等ではない。
    同じリクエストを繰り返しても、異なる結果が得られる可能性がある。
  • PUT
    PUTは冪等である。
    同じPUTリクエストを複数回送信しても、常に同じ結果が得られる。


POSTは、新しいリソースの作成に使用され、PUTは既存のリソースの更新に使用される。
PUTは冪等性があり、同じリクエストを複数回送信しても同じ結果が得られるため、更新操作に適している。