HTTPの歴史と技術の変遷

この記事は [Voicy Advent Calendar 2020](https://qiita.com/advent-calendar/2020/voicy) の 23 日目の記事です。
先日は, @yamagenii さんの [Goでmainが実行される様子をもっと追ってみる](https://medium.com/voicy-engineering/go%E3%81%A7main%E3%81%8C%E5%AE%9F%E8%A1%8C%E3%81%95%E3%82%8C%E3%82%8B%E6%A7%98%E5%AD%90%E3%82%92%E3%82%82%E3%81%A3%E3%81%A8%E8%BF%BD%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B-8ec4c0f61063) でした。明日は, @saicologic  さんの [エンジニアの仕事と死にゲーと私](https://qiita.com/saicologic/items/3b908acc888fedfc084a) です。

今回はWebエンジニアをする上で切っても切り離せないHTTPについてその歴史と技術の変遷を調べたので書いていければと思います。

## HTTPとは
正式名称はHypertext Transfer Protocol（ハイパーテキスト・トランスファー・プロトコル）です。

HTMLなどのテキストファイル、画像、そのほかの複合ファイルといったリソースを、効率的にクライアントへ配布するための通信プロトコルであり、ウェブページをブラウザで表示する時の、サーバーから情報をもらう際のルールに関する取り決めですが、その範囲を超えて、翻訳API、データ保存APIなど、さまざまなサービスのインタフェースとしても使われており、現在のインターネットの基盤となっています。

## HTTPのこれまでの変遷

HTTPは現在までに以下のような変遷をへています。未だに一般的に使用されているのはHTTP/1.1になりますが、それが世に出たのは1997年になります。その間にWebに関わる技術は大きく変遷して行ったのにも関わらずその基礎になるHTTPは20年近く1.1のままだったということになります。

1990年: HTTP/0.9
1996年: HTTP/1.0
1997年: HTTP/1.1
2015年: HTTP/2
2018年: HTTP/3

## HTTP1.1までの歴史
そんなHTTP1.1が公開される目での歴史はどんなものだったのでしょうか？

|  年  |  出来事  |
| ---- | ---- |
|  1989年  |  CERN（欧州素粒子物理学研究所）のティム・バーナーズ・リー（Tim Berners-Lee）氏が、WWW（World Wide Web）の基本的な仕組みを考案。転送プロトコルとして HTTP（HyperText Transfer Protocol）、リソースの識別名として URL（Unform Resource Locator）、ページ記述言語として SGML をベースとした HTML（HyperText Markup Language）を開発。  |
|  1990年  |  CERN、世界初の WWWサーバー と WWWブラウザ を試作。NeXT コンピュータを使用。HTML 1.0 のドラフト（草案）が検討される。HTML 1.0 はドラフトのまま廃案。  |
|  1993年  |  NCSA（米国 国立スーパーコンピューター応用センター）でHTMLとHTTPを実装したMosaicブラウザとNCSA HTTPサーバを開発。対応バージョンはHTTP0.9。無償公開を開始  |
|  1996年  |  Tim Berners-LeeらがHTTP1.0仕様（RFC1945）を公開  |
|  1997年  |  HTTP1.1公開  |

HTTPに関連しない部分の年テクノロジーに関わる年表は以下です。

|  年  |  出来事  |
| ---- | ---- |
|  1971年 |  Bolt Beranek & Newman社のレイ・トムリンスン（Ray Tomlinson）氏、電子メール を発明。 |
|  1986年| NEC社、パソコン通信サービス PC-VAN を開始。  |
|  1991年  |  ミネソタ大学、インターネットを利用した情報システム Gopher を開発。Gopher が完全階層（ツリー）型なのに対して、WWW が網（メッシュ）型を採用ティム・バーナーズ＝リー、世界初のWebサイトを公開。http://info.cern.ch/hypertext/WWW/TheProject.html ヴァンロッサム氏、Python 0.90 を公開。  |
|  1992年  |  AT&T Jens社、日本初の商用インターネットサービス SPIN を開始。ITU と ISO、共同で画像フォーマット JPEG を策定。  |
|  1993年  |  Mosaic 1.0 リリース |
|1994年|Amazon設立|
|  1995年  |  Java・PHP・Ruby・Internet Explorerなどが世に出る|


HTTP1.1が開発されるまでにこのような歴史があったのです。(ここで紹介する出来事はあくまで一部です)

## RFCとは
HTTPの話をする中で斬っても切り離せないのがRFCについて説明します。

RFCとはインターネット技術の標準化などを行うIETF（Internet Engineering Task Force）が発行している、技術仕様などについての文書群のことになります。TCP/IP関連のプロトコル（通信規約）の標準仕様などが記されたもので、インターネット上で公開されており誰でも入手・閲覧することが可能になっています。
インターネットのもとになったネットワークはアメリカの国防予算で作られたため、仕様を外部に公開できませんでした。そのため、「品質アップのためのご意見を広く世界から集める」という名目で仕様を公開することにした名残がこのRFC（request for comments）という名称になっています。

HTTP関連のRFCは以下のようにたくさんあります。

|  番号  |  内容  |
| ---- | ---- |
|  RFC2616  |  "Hypertext Transfer Protocol -- HTTP/1.1"  |
|  RFC2617  |  "HTTP Authentication: Basic and Digest Access Authentication"　Basic認証   |
|  RFC2068  |  "Hypertext Transfer Protocol -- HTTP/1.1"　最初のHTTP1.1仕様。2616に置き換えられている  |
|  RFC1945  |  "Hypertext Transfer Protocol -- HTTP/1.0"  |
|  RFC1738  |  "Uniform Resource Locators (URL)"  |
|  RFC1630  |  "Universal Resource Identifiers in WWW" URI仕様  |
|  RFC2965  |  "HTTP State Management Mechanism"　Cookieに関しての利用仕様。現在での正式最新版  |
|  RFC2109  |  "HTTP State Management Mechanism"　Cookieに関しての利用仕様  |

# 各HTTPの特徴

## HTTP/0.9
1991年に最初にドキュメント化されたバージョンです。

メソッドは GET しかありませんでした。レスポンスは単純にドキュメントの内容を返してコネクションを切断するだけで、レスポンスコードの規定もない。「HTMLのドキュメントを要求して取得するだけ」になります。

また、0.9と呼ばれるようになったのはHTTP/1.0の仕様が話題にされるようになってからです

特徴は以下

- １つのドキュメントを送る機能しかなかった
- 通信されるすべての内容はHTML文書であるという想定だったため、ダウンロードするコンテンツのフォーマットをサーバーから伝える手段がなかった
- クライアント側から検索のリクエストを送る以外のリクエストを送信できなかった
- 新しい文章を送信したり、更新したり、削除することはできなかった
- リクエストが正しかったか、もしくはサーバーが正しく応答を返すことができたかといった情報を知る方法もない


## HTTP/1.0
1996年5月に RFC1945 として発表され猿。メソッドに POST などGET以外のものが増えた形になります。レスポンスはヘッダーがつくようになり、ステータスコードを含めるようになりましら。また、HTTP/0.9 と区別するため、リクエストプロトコルにバージョンを含めることになりました。

この1.0で今でも残る4つの要素が形づくられました
・メソッドとパス
・ヘッダー
・ボディ
・ステータスコード


特徴は以下

- リクエスト時にメソッドが追加された
- リクエスト時にHTTPバージョンが追加された（HTTP/1.0）
- ヘッダーが追加された（Host、User-Agent、Acceptなど）
    - 先行していた電子メールのフォーマット(ヘッダー+本文)を取り入れた
- レスポンスの先頭にHTTPバージョンと3桁のステータスが含まれるようになった
    - ニュースグループからメソッドとステータスコードを取り入れた
- リクエストと同じ形式のヘッダーが含まれるようになった
- クッキーやBasic認証,Digest認証、プロキシ、セッションなどの定義も追加された


## HTTP/1.1
1997年1月に RFC 068 として初版が発表されました。その後、2回改訂。RFC7230から RFC7235 で規定されています。

HTTP/1.1は1997年に登場してから2015年のHTTP/2まで、20年近く最新バージョンでありつづけました。その間にHTML5が登場し、実際のアプリケーションも数多く作られ、ウェブの見た目は大きく変化したが、拡張性の高い仕組みとさまざまな用途に対応できる柔軟性のお陰で、HTTP/1.1は最新であり続けたのです。

HTTP/2の現在の仕様は、主に通信の高速化などの低レイヤーのコミュニケーションのシンタックスに特化しているため、通信内容やブラウザとサーバー間のコミュニケーションのセマンティクスの仕様としては今もHTTP/1.1で策定されている内容が残っています。

特徴は以下

- 通信の高速化
- Keep-Alive
    - 連続したリクエストにおいてコネクションを再利用し、TCP/IPの通信を高速化する仕組み
　クライアントとサーバの両方が設定を持ち、短いほうが採用される(デフォルトは、IEが60秒、FireFoxが115秒、　nginxが75秒、など)
- パイプライニング
    - 最初のリクエストが完了する前に次のリクエストを送信し、ネットワークの稼働率をあげる仕組み
- TLS(Transport Layer Security)による暗号化通信のサポート
　
    - TLSは通信経路を暗号化するプロトコル
　　要素技術:ハッシュ関数,共通鍵暗号,公開鍵暗号,デジタル署名,鍵交換(cf.DH,DHE)
- バーチャルホスト

    - 1つのウェブサーバーで異なるホームページを公開可能に

- PUTメソッドとDELETEメソッドの標準化
- OPTIONS、TRACE、CONNECTメソッドの追加
    - OPTIONS:サーバが受け取り可能なメソッド一覧を返す(nginxを含む多くのWebサーバでデフォルトOFF)
    - TRACE(TRACK):Content-Typeにmessage/httpを設定し200 OKで返す(XST脆弱性があり使われていない)
    - CONNECT:HTTPのプロトコル上に、他のプロトコルのパケットを流せるようにする

- チャンク
 - データ全体を一括で送信するのではなく小分けにして送信する方式 Trunsfer-Encoding: chunked


## HTTP/2.0
IETFのhttpbisワーキンググループがGoogleのSPDYプロトコル、（SPDYを基にした）マイクロソフトのHTTP Speed+Mobility、Network-Friendly HTTP Upgradeを検討。2012年7月にFacebookはそれぞれの提案にフィードバックを行い、HTTP/2はSPDYを基にすることを推奨しています。

SPDYをそのままコピーしたものを基にしたHTTP/2の最初のドラフトが2012年11月に発行されました。つまりGoogleの開発したSPDYというプロトコルが元担っていうます。これがほぼそのままHTTP/2となりました。

HTTP.1.1までとはデータ表現が大きく異なるが、通信アプリケーションから見れば大差はありません。

最大の特徴は、「1つのリクエストに対して1つのレスポンスを返す」というこれまでの基本構造を「ストリーム」という概念で壊したことになります。

特徴は以下です

#### HTTP1.1以前との比較
- ストリームによる通信の高速化
    - HTTP/1.1まで
        - ひとつのリクエストがTCPのソケットを専有するため、2〜6本のTCP接続を確立して並列化していた
クローズ状態からLISTENして、クライアントからの接続リクエストがあって初めてESTABLISH状態になる
        - アプリケーション層がはメソッドやパス、ステータスコードなどはヘッダ組み込まれており、実装上は「ヘッダ」「ボディ」のみ
テキストプロトコルであり、ヘッダの終端である空行まで1バイトずつ先読みする必要があるため、高度な並列化は難しい

    - HTTP/2
        - 1つのTCP接続の内部に、ストリームという仮想のTCPソケットを作り、「フレーム」という単位を送受信する
最初からLISTENとほぼ同じIDLE状態で、ヘッダを受け取ると即座に通信可能なOPEN状態になる
        - アプリケーション層がバイナリ化され、最初にフレームサイズが入っているため、TCPソケットのレイヤでデータをフレーム単位に分割できる

- フローコントロール
    - 通信先のウィンドウサイズ(受け取ることのできる空きバッファサイズ)を管理し、空いた分を埋めるようにデータを送る
- サーバプッシュ
    - CSSやJavaScript、画像などのうち、優先度の高いものをあらかじめサーバからクライアントに送信し、キャッシュしておく



## HTTP/3.0

IETF(Internet Engineering Task Force)において、HTTP-over-QUICが正式にHTTP/3という名前になりました。

QUICはGoogleによって開発された実験的なトランスポート層プロトコル→QUICプロトコルの上でHTTP(HTTP/2 API)を動かすための仕様です。

2019年9月26日に、Cloudflare、Google ChromeでHTTP/3のサポートが追加されましたが、HTTP/3が利用できるWebサーバーは、大手のものではLiteSpeedの有料版しかなく、NginxやApacheには対応していません。

仕組みは暗号化通信（SSL証明書の利用）が前提になっています。UDPを使って通信を行い、データ転送を行う前のコネクションの確立の手続きである「3wayハンドシェイク」が1往復減っているため、その分効率化されます。

TLS1.3には0-RTT（Zero Round Trip Time）という方式が追加されているため、セッション再開時にTLSハンドシェイク無しでデータ通信を開始することも可能です。

Googleの発表した論文によると、Googleの通信の30％がQUIC（HTTP/3）で行われており、Google Searchのレイテンシーをデスクトップで8％、スマートフォンで3％削減したと言われています。

## まとめ

以上が「HTTPの歴史と技術の変遷」になります。普段業務の中ではHTTPのようなプロトコルを深く意識することはないかもしれませんが、それぞれの特徴を知っておくことはインフラの構築やAPIの設計などで役に立つ場面は少なくないように思います。

今回の記事が読む方に少しでもプラスになれば幸いです。

最後までお読みいただきありがとうございました。