【ネットワーク】HTTPの基礎（概要メモ）

# はじめに
業務をする中でネットワークのやWebなどITの土台となる知識が足りていないと感じたため、書籍や記事を参考に自分なりに整理してみた。今後は詳細部分について記事にしていく予定です。

# HTTPとは
HTTPとは「HyperText Transfer Protocol」の略でWebクライアントとWebサーバとの間でデータの送受信を行うために使用されるプロトコルです。
直訳とすると「HTMLファイル等のハイパーテキストを転送する際に使用される通信のルール」 という意味になりますが、実際にはHTMLファイルやXMLファイル等のハイパーテキストだけでなく、CSSやJavaScript、画像や動画等コンピュータで扱えるデータであれば何でも転送できます。

### OSI参照モデル
OSI参照モデルとはコンピュータネットワークで必要となる複数のプロトコルについて、それぞれの役割を分類し、明確化するためのモデルです。
HTTPはOSI参照モデルでいう第7層にあたるアプリケーション層で使用されるプロトコルです。
![スクリーンショット 2022-01-23 13.28.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646903/b0b0b913-3be0-d8e6-5d58-4cd3814da453.png)

### バージョン
HTTPにはバージョンがあり、どれも、IETFによって定義されています。アップデートされることでメソッドが追加されたり、通信速度の改善に成功しています。
現在はHTTP/1.1もしくはHTTP/2.0が使用されることが多いですが、最近では3.0の仕様策定も進んでいるそうです。

|年|バージョン|
|-|-|
|1990年 |HTTP/0.9  |
|1996年  |HTTP/1.0  |
|1997年  |HTTP/1.1  |
|2015年  |HTTP/2  |
|2018年  |HTTP/3  |

### HTTPS
* HTTPSとはHTTPにSecureのSが追加されたもので、データのやり取りを暗号化してより安全な通信を担保します。

* HTTPには通信の暗号化についての仕様が存在していないため、暗号化プロトコルのSSL（Secure Socket Layer）やその後継者であるTLS（Transport Layer Security）で暗号化した上でHTTP通信を行う方式（= HTTP over SSL/TLS）をとり、通信の安全性を保っています。

* HTTPは標準でTCPの80番ポートを使用して通信するが、HTTPSは標準でTCPの443番ポートが使われます。

#### 暗号化されていないページのアドレス欄
![スクリーンショット 2021-11-29 0.55.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646903/a7fb13cc-0305-0e7c-16c4-677fe6f38bc3.png)
#### HTTPS化されたページのアドレス欄
![スクリーンショット 2021-11-29 0.55.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646903/f9737537-d824-1099-4ed5-893e5b4f2ec9.png)

# HTTPリクエストとHTTPレスポンス
Webはアーキテクチャスタイルとしてクライアント/サーバモデルが採用されています。
クライアントとサーバとの間でHTTPメッセージを送受信することで効率的かつ安全な通信を可能としています。
![スクリーンショット 2021-11-29 20.59.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646903/56eaa1de-8b7c-d52f-5976-ac71eaecc2fa.png)

# HTTPメッセージ
Webブラウザ等のクライアントがサーバに対して送るHTTPメッセージをリクエストメッセージ、サーバがクライアントに対して送るHTTPメッセージをレスポンスメッセージといいます。
### HTTPメッセージの構造
リクエストメッセージ、レスポンスメッセージともに以下のようにスタートライン、ヘッダが並び、一行空けてボディが続く形式となっています。
<img width="300" alt="スクリーンショット 2021-11-29 1.13.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646903/1ff78963-36c8-7835-b14f-01215aa5487a.png">

## スタートライン
スタートラインについては以下のようにリクエストメッセージとレスポンスメッセージで名称が変わります。

|||
|-|-|
|リクエストメッセージのスタートライン |リクエストライン  |
|レスポンスメッセージのスタートライン  |ステータスライン |

### 【リクエストライン】
![スクリーンショット 2021-11-29 2.22.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646903/9376e0bd-2746-fcb5-c1b0-1812baff3d0d.png)

「**どのようなリソースに対してどんな操作をしたいか**」という情報

リクエストラインは以下の3つで構成されています。

* HTTPメソッド
    * GET, POST, DELETEなど次のURIで示すリソースに対する操作を表す
* リクエストURI
    * サーバ上に存在するリソースを一意に特定するための識別子
* プロトコルバージョン
    * プロトコルのバージョン

### 【ステータスライン】
![スクリーンショット 2021-11-29 2.25.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646903/79eed086-0a2a-5077-5e96-a306ff6b935d.png)

ステータスラインは以下の3つで構成されています。

* プロトコルバージョン
    * プロトコルのバージョン
* ステータスコード
    * レスポンスの種類を示す番号（200, 404 など）
* リーズンフレーズ(Reason Phrase)
    * レスポンスの種類を示す文字列（"OK", "Not Found" など）

## HTTPヘッダ
* HTTPリクエストやHTTPレスポンスをする際クライアントやサーバが追加するメタデータのこと。
* `ヘッダー名: 値`という形式で定義される

#### 代表的なヘッダ
* User-Agent
* Referer
* Authorization
* Accept
* Content-Type
* Content-Length
* Content-Language
* Date
* Transfer-Encoding
* Authorization
* Cach-Control

## 実際にメッセージを確認してみる

実際にgoogle.comに`curl`コマンドでアクセスして確認してみます。
-v (verbose, 詳細)オプションをつけることでいろいろと情報が表示されます。

```
$ curl -v https://www.google.com
```

### リクエストメッセージ
以下はリクエストメッセージの部分を抜粋した結果です。

```
> GET / HTTP/2
> Host: www.google.com
> User-Agent: curl/7.64.1
> Accept: */*
>
```
* リクエストライン
    * `GET / HTTP/2`
        * 今回はGoogleのサーバに`GET`メソッドで`/`にあるリソースの取得を要求していることがわかります
* ヘッダ
    * `Host: www.google.com`
        * サーバーのドメイン名
    * `User-Agent: curl/7.64.1`
        * リクエストを行うソフトウェアのアプリケーションタイプ
        * Webブラウザや今回のような`curl`が格納されます。
    * `Accept: */*`
        * クライアントが理解できるコンテンツタイプをMIMEタイプで表したもの。
* 空行
* ボディ
    * なし



### レスポンスメッセージ
以下はレスポンスメッセージの部分を抜粋した結果です。

```
< HTTP/2 200
< date: Sun, 28 Nov 2021 16:23:46 GMT
< expires: -1
< cache-control: private, max-age=0
< content-type: text/html; charset=ISO-8859-1
< p3p: CP="This is not a P3P policy! See g.co/p3phelp for more info."
< server: gws
< x-xss-protection: 0
< x-frame-options: SAMEORIGIN
< set-cookie: 1P_JAR=2021-11-28-16; expires=Tue, 28-Dec-2021 16:23:46 GMT; path=/; domain=.google.com; Secure
< set-cookie: NID=511=n2W92v5Ts8Wdv-hgm2ZsGTGPugP5_gA-CKlAqIGvJjVpB2UOCIDmw5yT7RoPUJQ2Jp6aX_8W2bA1t5aTQE28kYuqNK7VzrqZsQisUkg6MJsYYyEXp70rXUmyg_Xj74ddI3Ghxfac-Mhb-xEAdH9tmMiabJqz_RZDpC-q5swT2NY; expires=Mon, 30-May-2022 16:23:46 GMT; path=/; domain=.google.com; HttpOnly
< alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
< accept-ranges: none
< vary: Accept-Encoding
<
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="ja"><head><meta content="&#19............................
```
* ステータスライン
    * `HTTP/2 200`
        * プロトコルのバージョンがHTTP/2
        * 200番、つまり「リクエストが成功した」という情報が返却されています。
* ヘッダ
    * `date: Sun, 28 Nov 2021 16:23:46 GMT`
        * メッセージを生成した日付
    * `cache-control: private, max-age=0`
        * キャッシュに関する指示
    * `content-type: text/html; charset=ISO-8859-1`
        * リソースのメディア種別
            * htmlやjson、画像など。
* 空行
* ボディ
    * 今回はHTMLがクライアントへレスポンスされています。

# HTTPのステートレス性
コンピュータネットワークにおけるプロトコルには**ステートフル**なプロトコルと**ステートレス**なプロトコルが存在します。
HTTPは**ステートレス**なプロトコルとして設計されています。

### ステートフルとは
* サーバがアプリケーション状態を保存する
* サーバが過去のやり取りにおける情報を全て記憶して、その情報を処理結果に反映する
* FTP（ファイルを送受信するときに使用するプロトコル）はステートフルでカレントディレクトリ等の情報をサーバ側が都度記憶している。

### ステートレスとは
* サーバがクライアントのアプリケーション状態を保存しない
* サーバは過去のやり取りにおける情報は保存しないため、クライアントの状態をいちいち把握しない

[こちら](https://blog.proglearn.com/wp-content/uploads/2020/09/stateless.pdf)の資料をみるとわかりやすいですが、自分たちがする日常的な会話は基本**ステートフル**です。どんな状況でも**ステートフル**の方が、簡潔で優れているように思ってしまったのですが、HTTPが**ステートレス**で設計されたのにはもちろんですが理由があるようです。

### ステートフルのデメリット
* クライアントのアプリケーション状態を常に把握する必要があるのでサーバに負荷がかかる。
* クライアントの数が増え複数台のサーバを設置する場合、不特定多数のクライアントに対応するため複数のサーバでアプリケーション状態を同期する必要がある。

つまり、ステートフルはスケールアウトさせにくいというデメリットがあります。

### ステートレスのメリット
ステートレスでは上記のステートフルのデメリットを解消することができます。

* クライアントが必要な情報を全てリクエストメッセージに含めてくれるのでサーバ側の負荷が少ない。
* クライアントのアプリケーション状態を気にせず、新しく送られてくるリクエストに集中できる。

つまり、クライアントが増えても、単純にサーバを増やせばいいのでスケールアウトが容易になります。

ただ、クライアントは毎回必要な情報を全て送信する必要があるため、データ量が多くなり、ネットワーク帯域を消費する可能性があるデメリットもあります。

# おわりに
* HTTPの基本的な役割や立ち位置、特性等を改めて認識することができた。
* より理解を深めるために普段からHTTPの役割やメッセージの内容などを意識して業務に取り組みたい。

# 参考
* 『Webを支える技術』
* 『Webブラウザセキュリティ』
* https://www.seraku.co.jp/tectec-note/industry/osi-reference-model/
* https://developer.mozilla.org/ja/docs/Web/HTTP
* https://blog.proglearn.com/wp-content/uploads/2020/09/stateless.pdf
* https://www.redhat.com/ja/topics/cloud-native-apps/stateful-vs-stateless