Webの世界-HTTP基礎編-

# Webの世界-HTTP基礎編-
## 概要
今日利用されるWebは様々な技術の集合体で成り立っている。  
画面を構成するHTMLやCSS、JavaScriptなどの言語類などがよく取り上げられるが、一番基本となるクライアントとサーバー間の通信の取り決めとなるHTTPについて本記事で解説する。


## HTTPとは
### 概要
HTTPはHypertext Transfer Protocolの略でWebブラウザなどのクライアントとWebサーバーが通信する際の手順とフォーマットを規格化したものになる。  
OSI階層で言うとアプリケーション層となり、実際の通信管理はトランスポート層のレイヤ(主にTCP)が使用される。  
概略図を下記に示す。
![HTTP概要.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/292905/169b2447-9a22-dbd6-7cf1-d1081dc71369.png)
実際に通信する内容は、リクエストの場合はメソッドやURLを含む**開始行**、レスポンスの場合はステータスコードなどを含む**ステータス行**と通信時に必要な情報などがまとめられた**ヘッダー**とHTMLやJSONなど送りたい情報を含む**ボディ**に大別され、通信する際は``開始行+ヘッダー+(ボディ)``もしくは``ステータス行+ヘッダー+ボディ``でまとめて送りあう。  
基本的にクライアント側は「何を」「どうする」をサーバーに要求し、サーバーはその結果をHTTPの形式にのっとって返信するだけになる。  
そのため、仮に同じクライアントが同じサーバーに連続してリクエストしたとしても、各リクエストに関係性はなく**ステートレス**である。  

### 種類
HTTPも環境の変化などから都度アップデートされており、複数のバージョンが存在する。  
w3techs(https://w3techs.com/technologies/overview/site_element/all) によると、2019/11月現在、約40%がHTTP/2.0を使用しているとされている。
HTTP/2.0とHTTP/1.1は完全な互換性があり、実生活でブラウジングなどを楽しむだけであればあまり意識する必要がない。  
各種仕様は[IETF(Internet Engineering Task Force)](https://ietf.org/)が策定し、RFC(Request for Comments)という形で公開されている。  
各バージョンを簡単に紹介する。

#### HTTP/0.9
HTTPの一番最初の実装。  
当初からHTTP/0.9と呼ばれていたわけではなく、HTTP/1.0ができたためその前のバージョンということでHTTP/0.9と呼ばれるようになった。 
基本的にはクライアントがサーバーにHTMLのドキュメントを要求して取得するだけのプロトコルであったが、都度機能拡張して行き、HTTP/1.0につながることになる。  
現在使用されているプロトコルとは互換性がないため、基本的には使用できない。

#### HTTP/1.0
電子メールで使われていたプロトコルなどを取り込む形でHTTP/0.9を大幅にアップデートした仕様。  
変更点は下記の通り

リクエスト

+ メソッドの追加
+ HTTPバージョンの情報の追加
+ ヘッダーの追加

レスポンス

+ HTTPバージョンの情報の追加
+ ステータスコードの追加
+ ヘッダーの追加

できるようになった事

+ 複数のドキュメントが送信可能になった
+ HTML以外のデータ形式に対応
+ サーバーのコンテンツの追加、削除、更新が行えるようになった
+ リダイレクトが行えるようになった

以降のHTTPの大枠はこの時策定されているものから大きく変わってはいない。

#### HTTP/1.1
HTTP/1.0から大きな変更はないが、通信の高速化などで取り入れられた機能がある。
追加された機能は以下の通り

+ Keep-Aliveがデフォルトで有効になる
+ パイプライニング機能が追加
+ TLSによる暗号化通信のサポート
+ 新メソッドが追加(OPTION,TRACE,CONNECT)

Keep-Aliveとパイプライニングは詳しく説明しないが、どちらも通信の高速化を狙った機能になる。パイプライニングはこの時点では意図したような高速化は得られなかったが、今後の発展につながる。

#### HTTP/2.0
HTTP/1.1が規定されて以来16年ぶりのバージョンアップになる。  
基本的な部分ではHTTP/1.1から変化はないが、より高速化を意識した機能が追加されている。  
追加されたものは以下の通り  

+ ストリームによりバイナリデータを多重に送受信できるようになる
+ ストリーム内の優先順位の設定
+ サーバーサイドからデータ通信を行うサーバープッシュの実装
+ ヘッダーを圧縮するようになる

また、HTTP、HTTPSどちらの実装も存在するが、各種ブラウザがHTTPSでの実装しか対応していないため、実質的にHTTP/2.0を使用する場合はHTTPSが必須となる。  

#### HTTP/3.0(旧QUIC)
Googleが以前から開発していた[QUIC](https://www.chromium.org/quic)をベースとしたHTTP-over-QUICをHTTP/3.0と呼称する。  
HTTP/3.0は今までのHTTPとは大きく異なり、TCP上ではなく、UDP上で動作する。  
詳しい説明は省くが、セキュリティの強化とレイテンシの削減が目玉となる。  
現在ではChromeなどでサポートがされているが、まだ主流とはなっていない。

#### HTTPS
今まで紹介したものとは異なり、HTTPS自体はプロトコルではなく、SSL/TLSプロトコルを使用したセキュアな接続でHTTP通信を行うことをHTTPSと呼ぶ。  
通常、HTTPでの通信は平文でやりとりされているため、通信内容の傍受や改ざんなどが可能であり、プロキシサーバーによって中身を書き換える通信方法などが用いられていることもある。    
HTTPSでは公開鍵暗号方式、および共通鍵暗号方式を用いたハイブリット方式により、通信内容が暗号化されているため、通信内容の傍受が不可能となっている。  

2019/11月現在一部で話題(炎上)となったが、基本的に通信の安全性を担保するだけで、通信先などHTTPによる通信が関与しない部分での安全性は一切担保されない。
### 基本要素
HTTPプロトコルは前述したように様々なバージョンが存在するが、その基本となる要素はほとんど変化していない。  
すなわち、

+ メソッドとパスによってどのサーバーに何を要求する。
+ ヘッダーでコンテンツの種類やその他通信に必要な要素をやり取りする。
+ ボディで要求した情報やPOSTする情報をやり取りする。
+ サーバーの応答状況の確認をする。
以上の要素である。 
各要素はリクエストおよびレスポンスのメッセージで以下のような構造でやり取りを行う。

```:リクエスト
<開始行(メソッドとパス)>
<ヘッダー(複数行)>
!-- 一行空白 --!
<ボディ>
``` 

```:レスポンス
<ステータス行>
<ヘッダー(複数行)>
!-- 一行空白 --!
<ボディ>
``` 
以下で各要素をもう少し詳しく解説する。

#### メソッドとパス(とプロトコルのバージョン)
前述したように、メソッドとパスを用いてどのサーバーに対してどんな要求をするかを伝える役目を持つ。  
メソッドとパスはリクエスト時の開始行に記述され、以下のような構造を持つ。

```:開始行
メソッド パス プロトコルのバージョン
```

メソッドは基本的には以下のものが定義されている

+ GET : パスで指定したファイルorプログラムの出力を要求
+ HEAD : GETと同様だが、ヘッダのみ返す
+ POST : key-valueの形式でサーバーに値を渡す。値はボディに記述される
+ OPTIONS : サーバーが受け取り可能なメソッド一覧を返す
+ PUT : パスで指定したサーバ上のファイルを置き換える
+ DELETE : パスで指定したサーバ上のファイルを削除する
+ TRACE : サーバーが受け取ったヘッダーとボディをそのまま返す
+ CONNECT : HTTPのプロトコル上にほかのプロトコルのパケットを流せるようにする

主に使うのはGET/POST/DELETE/PUTだと思われる。これによりCRUD操作が実現できる。  
メソッドでどうするかを指定し、パスでどこに要求するかを定める。
パス自体は`/`からはじまり、サーバ上の階層のどこを指すか指定するが、実際にHTTP通信を行う場合はこれにスキーマとホスト名を加えた以下のようなURLの構造をブラウザなどのクライアントに指定する必要がある。

```:URL
スキーマ://ホスト名/パス
```
開始行に記述されるのはパスの部分だけだが、クライアント側がそれ以前のスキーマとホスト名から接続先のサーバを探してくれる。  
接続先の決定はHTTPレイヤの話ではないため割愛する。

#### ヘッダー
ヘッダー部分は実に様々な情報を記述でき、```フィールド名:値```の形で表わされる。  
以下に抜粋して示す。  
なお、フィールド名に```X-```を付与して独自のヘッダーを記述することもできる。  

クライアントから送付するヘッダー

+ User-Agent : クライアントが自身のアプリケーション名(Chrome,curlなど)を記述する
+ Authorization : 認証情報をサーバーに伝える
+ Cookie : クッキー  
  
サーバから送付するヘッダー

+ Content-Type : 返却するファイルの種類(MIMEタイプ)を指定する
+ Content-Length : ボディのサイズを伝える
+ Date: ドキュメントの日時

#### ボディ
こちらも様々な情報を記述できるが、記述内容はコンテンツの種類による。  
HTMLであれば当然HTMLが記述され、JSONであればJSONが記述される。  
なお、GETメソッドでもボディに情報を詰めて送ることはできるが、推奨はされない。
#### ステータスコード
3桁の数字でサーバがどのように応答したのかを表す。  
大きく以下のような分け方となる。

+ 100番台 : 特殊用途
+ 200番台 : リクエスト成功
+ 300番台 : リクエストは成功しているが、サーバからクライアントへ要求がある
+ 400番台 : クライアントからのリクエストにおかしいところがある
+ 500番台 : サーバ内部でエラーが発生
  
## まとめ
以上がHTTPの基礎編となる。  
こういった基本的な知識はあまり変化しない上、つぶしが効く知識だなと思うので、個人的にもしっかり学んでいければと思います。  
次はHTTPの発展編かブラウザの仕組みなどを解説できれば…