HTTPについてちゃんと理解する

## HTTPとは

**HTTPとは、WebサーバとWebクライアントがデータを送受信するために利用されるプロトコルのこと**です。

HTTPはHyper Text Transfer Protocolの略で、ハイパーテキストを転送するプロトコルという意味ですが、ハイパーテキストであるHTML以外にも、CSSやJavaScript、画像、動画、PDFなど**コンピュータが扱えるデータならなんでも転送できる**ようです。

プロトコルについての説明は不要かもしれませんが、念のために書くと、コンピュータ同士が通信するときの規格や手順を定めた約束事です。異なるメーカの機器であっても、規定のプロトコルに従っていれば通信することができます。HTTPというプロトコルに従っていれば、どんなコンピュータもWeb上でやりとりすることができる、ということだと私は理解しています。

HTTPの特徴をまとめると次のようになります。

* OSI参照モデルのアプリケーション 層を担うプロトコル
* ステートレスにすることで大量のリクエストを高速に処理
* ログイン状態やカート情報を保持するためにCookieを使用

これらの特徴について簡単にまとめていきます。

### OSI参照モデルにおける位置づけ

HTTPは、**OSI参照モデルの第7層アプリケーション層を担うプロトコル**です。

OSI参照モデルとは、通信におけるプロトコルを7つのレイヤに抽象化することで、プロトコルの変更があっても他のレイヤは影響を受けないように設計されたモデルです。HTTPが担うアプリケーション層はOSI参照モデルの最上位のレイヤです。たとえばコンピュータをつなぐ物理的なケーブルが何であるかは、WebサーバとWebクライアントがデータを送受信するときの手順に影響しません。

Webを利用するとき、アプリケーション層ではHTTPが使用されていますが、トランスポート層ではTCP、インターネット層ではIPというプロトコルが使用されます。HTTPという単一のプロトコルだけでWebが実現しているわけではありません。

クライアントとサーバのデータ送受信の流れは、おおまかに次のようになります。

1. クライアントがブラウザにURLを入力する
2. クライアントからサーバにHTTPリクエストを送信する
3. サーバはHTTPリクエストに対応するHTTPレスポンスをクライアントに送信する
4. クライアントはブラウザにWebページを表示する

**このうち、HTTPが使われるのは2.と3.の部分**です。HTTPリクエストとHTTPレスポンスをまとめてHTTPメッセージといいます。

### ステートフルかステートレスか

HTTPはステートレスなプロトコルです。1回やりとりをするたびに接続が切れることをステートレスと表現するようです。

※ ステートレスについては、[こちらのRESTの記事](https://qiita.com/yuta-o-note/items/6b24ae9013bde35a132b#%E3%82%B9%E3%83%86%E3%83%BC%E3%83%88%E3%83%AC%E3%82%B9%E3%82%B5%E3%83%BC%E3%83%90)でも詳しく書きましたので、ご興味のある方は参考にしてください

FTPやSMTPは、HTTPと同じアプリケーション層のプロトコルですが、HTTPとは違いステートフルです。たとえば、SMTPはEメール送信のためのプロトコルですが、コマンドラインから送信内容を入力する際、最初にメールサーバの情報、次に送信者のメールアドレス、受信者のメールアドレス、とひとつずつ決まった順番で入力していくようです。**Eメールの送信に必要な情報をまとめて入力するのではなく、ひとつの項目ずつ入力することができる**のは、それまでに入力した内容をすべて記憶しているからです。このようなプロトコルはステートフルといわれます。

一方、**HTTPはステートレスなので、処理に必要なすべての情報をひとつのリクエストにまとめる必要があります**。たとえば新しくユーザを登録する際、入力必須の項目に漏れがあったとすると、「未入力の項目があります」とエラーが返ります。このとき、未入力の項目を埋めて再度リクエストを送信することになりますが、一度目のリクエストで送信した入力項目も一緒に送信する必要があります。サーバは最初のリクエストで何が送信されたのかを、レスポンスを返した直後に忘れてしまうからです。

ステートレスなプロトコルの利点は、レスポンスを返した直後にサーバのリソースを自由にできることにあるようです。

サーバが多数のクライアントの状態を保持し、クライアントごとに状態に応じた処理をするのは負荷がかかります。ステートレスにすることで、こうしたオーバヘッドがかからなくなります。また、トラフィックを分散するためにサーバの台数を増やしたくなった場合、サーバごとにセッション情報を保持しているとそれらを同期する必要が生じ、さらに負荷が増大することになります。

### Webサービスが状態を管理する仕組み

HTTPはステートレスですが、ログイン状態やショッピングカートの中身を管理する仕組みは必要です。そのための仕組みとしてCookieがあります。

Cookieとは、サーバ側がWebブラウザに任意の情報を保存させる仕組み、あるいは保存させたデータのことのようです。

サーバは、Webブラウザに保存して欲しい情報をレスポンスのヘッダに`Set-Cookie`という名前で含めます。Webブラウザは、受け取ったCookieを保存して、次のリクエストのヘッダに`Cookie`という名前で含めます。このようにして、ステートレスなHTTPでもセッション状態の管理が実現できているようです。

## インターネットとWebの違い

実はHTTPについて説明するとき、「インターネットを通じてデータを送受信するためのプロトコル」と書こうとしたのですが、思い留まりました。インターネットとWebは違うものだからです。しかし、それぞれの意味の違いを理解していなかったので、インターネットとWebの違いについても簡単に整理してみました。

### インターネットとは

インターネットとは、インターネットプロトコル（IP）を利用した通信網のことのようです。略してネットと呼ばれます。

IP電話はインターネットプロトコルを利用した電話なので、インターネットを介した電話と表現できると思います。同様に、Eメールの送受信などもインターネットを利用しています。喩えるなら、インターネットは世界規模でコンピュータ同士の接続を実現する道のようなものでしょうか。

### Webとは

Webとは、インターネットを利用したハイパーテキストの公開および閲覧システムのことのようです。

WebはWorld Wide Webの略ですので、両者は同じものです。wwwと略されることもあります。

EメールやIP電話と同様に、Webもインターネットを利用した技術のひとつです。Webはインターネットという集合の要素のひとつ、というような説明を読みましたが、正確には、Webはインターネットを利用した技術のひとつ、ではないかと思います。インターネットは通信網のことですが、Webは通信網を利用したシステムを指すからです。

ハイパーテキストというのは、テキスト内で他のテキストを参照できる仕組みです。この説明を初めて読んだのは中学生のときで、「索引がいらなくなるな」という感想を持った程度でした。そのときは、外部ファイルを読み込んで見た目を整えたり、画像や動画を埋め込んだりといったことができるとは知りませんでした。

### 定義の違い

改めて整理すると、インターネットはIP通信を利用した通信網のことで、Webはインターネットを利用してハイパーテキストの公開や閲覧をするシステムのことです。インターネットを利用した技術には、EメールやIP電話などいろいろありますが、Webもそれらのひとつです。

## HTTPとHTTPSの違い

HTTPSも、HTTPと同様にWebサーバとWebクライアントがデータを送受信するためのプロトコルですが、通信内容が暗号化されているという点が違います。

HTTPSの最後の「S」はSecureで、HTTPSよりも安全なプロトコルであることを意味します。HTTPSの暗号化にはSSL（Secure Socket Layer）というプロトコルが使用されていましたが、現在ではTLS（Transport Layer Security）というプロトコルが使われています。しかし、SSLという言葉が長く使われていた名残で、WebサービスのプロトコルをHTTPからHTTPSに切り替えることを、現在でもSSL化と表現するようです。

### HTTPが安全でない理由

HTTPを利用した通信には、次のようなセキュリティリスクが潜在するようです。

* なりすまし
* 中間者攻撃
* 盗聴

**なりすまし**

なりすましは、たとえば税金の振込や商品購入の決済のための入力フォームを本物そっくりに作成し、お金や個人情報をだまし取る手法です。フィッシング詐欺ともいわれます。HTTPSでは、サーバとクライアント間の通信内容が改竄されていると、改竄されたことがわかるようになっているようです。

**中間者攻撃**

中間者攻撃は、暗号化されていない公共の無線LANやネットワークの中継地点を偽装して、サーバとクライアントの間に不正に割り込む手法です。通常のHTTPでは、中間者攻撃により通信内容の改竄や盗聴が行われるリスクがあるのですが、HTTPSによる暗号化することでそれらを防ぐことができるようです。

**盗聴**

HTTPでは、通信内容はパケットと呼ばれる小さなデータに分割して送受信されますが、このパケットは平文（テキストのまま）なのだそうです。そのため、通信が第三者に傍受されると、それが復元され、内容が盗聴されるリスクがあります。一方、HTTPSにより通信内容を暗号化しておけば、仮に第三者にデータが渡っても簡単には復元できないため被害の拡大を抑えることができるようです。

### HTTPSの安全面以外のメリット

これは蛇足ですが、常時SSLのメリットは安全面以外にもあるようです。

* 検索順位が上がる
* リファラ情報が活用できる
* HTTP/2による高速化

**検索順位が上がる**

Googleが検索順位の決定要因のひとつに「HTTPSかどうか」を含むと公表しているようです。そのため、コンテンツが同じであればHTTPよりもHTTPSのほうが検索順位は上位になります。

**リファラ情報が活用できる**

ユーザがGoogleで検索した結果をクリックしてページ遷移する場合、遷移先のページがHTTPSであれば「Google検索から訪問したユーザ」としてアクセスログに残るようです。そういったリファラ情報はHTTPのページでは送信されないため、分析に不利になるようです。

**HTTP/2による高速化**

HTTP/2というモバイル機器でのウェブ表示を高速化するためのプロトコルがあり、これを利用するためにはSSL暗号化が必須なのだそうです。以前はHTTPSを採用するとサーバの負荷が増大し、通信速度が低下するといわれたらしいのですが、現在のコンピュータのスペックなら暗号化にかかる時間は実感できないほど短く、HTTPSにするメリットのほうが大きいそうです。

## HTTPメッセージの構成

HTTPのリクエストとレスポンスを総称してHTTPメッセージというようです。

HTTPメッセージは、ASCIIという文字コードでエンコードされたテキストで構成されています。リクエストもレスポンスも似た構造になっていて、スタートライン、ヘッダ、ボディなどの要素が改行で区切られて配置されています。

* スタートライン
  * HTTPメッセージの一行目
  * リクエストではリクエストラインと呼ばれる
  * レスポンスではステータスラインと呼ばれる
* ヘッダ
  * `名前:値`の形式で格納される
  * 例：`Host:example.com`
* 空行
  * ヘッダとボディを区別するための空行
* ボディ
  * テキストだけでなくバイナリデータも入れられる
  * 例：`<html> ~略~ </html>`
  * 省略可能

HTTPメッセージは、WebブラウザやWebサーバといったソフトウェアが作成するため、ソフトウェア開発者が自前で作成することはめったにないそうです。

### リクエストメッセージの構成

* リクエストライン
  * メソッドとURIとプロトコルバージョンを含む
  * 例：`GET /serch?q=test HTTP/1.1`
* ヘッダ
  * メッセージのメタデータ
  * 例：`Host:example.com`
* ボディ
  * リソースの作成や更新の際に入る

### レスポンスメッセージの構成

* ステータスライン
  * プロトコルバージョンとステータスコードとテキストフレーズを含む
  * 例：`HTTP/1.1 200 OK`
* ヘッダ
  * コンテンツタイプや文字エンコーディング方式などのメタデータ
  * 例：`Content-Type:application/xhtml+xml`
  * 例：`charset:utf-8`
* ボディ
  * HTMLなどのリソースの表現

### HTTPメソッドの種類

HTTPメソッドには次のような種類があるようです。

> | メソッド | 意味                                                     |
> | :------- | -------------------------------------------------------- |
> | GET      | リソースの取得                                           |
> | POST     | 子リソースの作成、リソースへのデータ追加、そのほかの処理 |
> | PUT      | リソースの更新、リソースの作成                           |
> | DELETE   | リソースの削除                                           |
> | HEAD     | リソースのヘッダ (メタデータの取得)                      |
> | OPTIONS  | リソースがサポートしているメソッドの取得                 |
> | TRACE    | プロキシ動作の確認                                       |
> | CONNECT  | プロキシ動作のトンネル接続への変更                       |
>
> [Webを支える技術](https://www.amazon.co.jp/Web%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93-HTTP%E3%80%81URI%E3%80%81HTML%E3%80%81%E3%81%9D%E3%81%97%E3%81%A6REST-WEB-PRESS-plus/dp/4774142042)

このうち、よく利用するのは上の5つくらいです。

HTTPメソッドを上記のように限定してインタフェースを統一することにより、クライアントとサーバの独立性を高めています。たとえばサーバとクライアントの間にプロキシを設置して階層化しても、クライアントは接続先がサーバであるかプロキシであるかを意識しなくて済みます。[こちらの記事](https://qiita.com/yuta-o-note/items/6b24ae9013bde35a132b#%E7%B5%B1%E4%B8%80%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9)に詳しく書きましたので、よければ参考にしてください。

## HTTPバージョン遷移

HTTPはWebの仕組みを利用してデータを送受信するためのプロトコルですが、1990年に誕生して以来、何度かバージョンアップされているようです。2020年8月現時点では、おそらくHTTP/3が最新バージョンのようです。

HTTPの各バージョンが作られた時期と特徴を簡単にまとめてみます。

| バージョン | 時期 | 特徴                                                         |
| ---------- | ---- | ------------------------------------------------------------ |
| HTTP/0.9   | 1990 | **使用可能なメソッドはGETのみ**<br />リクエストはメソッド名とリソースのパスだけのワンラインプロトコル<br />レスポンスはファイル自身のみでヘッダやステータスコードもない |
| HTTP/1.0   | 1996 | プロトコルのバージョンをスタートラインに含む<br />レスポンスの**ステータスラインでリクエストの成功失敗を判定**する<br />ヘッダにメタデータを含めることで**HTML以外のファイルも転送可能になった** |
| HTTP/1.1   | 1997 | **通信内容を暗号化するためのTLSというプロトコルをサポート**<br />パイプライン機能の追加などによる通信のレイテンシの削減 |
| HTTP/2     | 2015 | **高速化されたプロトコル**<br />テキスト形式ではなくバイナリ形式のプロトコル<br />同じコネクションで複数のリクエストを並行して処理できる |
| HTTP/3     | 2018 | トランスポート層に**TCP/TLSの代わりにQUICというプロトコルを使用する**<br />QUICにより従来よりハンドシェイクが早い |

バージョンに関するまとめは、次のページを参考にさせていただきました。

※ [HTTP の進化](https://developer.mozilla.org/ja/docs/Web/HTTP/Basics_of_HTTP/Evolution_of_HTTP)
※ [HTTPのバージョンについてまとめ](https://qiita.com/hirooka0527/items/13767855358f83db5e02)

## まとめ

HTTPとは、Webにおいてクライアントとサーバがデータを送受信するときに利用するプロトコルのことでした。

インターネットはIPを利用した通信網のことで、Webはインターネットを利用してハイパーテキストを公開・閲覧するためのシステムです。初期のHTTPでは、送受信できるのはHTMLファイルのみだったようですが、HTTP/1.0以降はコンピュータが扱えるデータであれば何でも送受信できるようになりました。

Cookieの仕組みやHTTPのバージョンごとの詳しい違いについて、もっとちゃんと理解したいと思いました。機会があればまた記事を投稿したいと考えています。