Web API入門#5 〜HTTPの基礎〜

## はじめに

タイトルについて記事にしました。
この記事で得る内容は以下の通りです。

・ TCP/IPの4階層モデル、HTTPのバージョン、リクエストとレスポンスの流れ、HTTPメッセージ
・ Web APIの動きについての確認方法

HTTPの基礎を学習することで、Webにおける通信の基礎を理解することができます。

■ Web API入門についての過去記事
・ [Web API入門#1 〜APIとWeb API、Webの概要〜](https://qiita.com/s79ns/items/8dd2f06145cbf9464b99)
・ [Web API入門#2 〜REST、アーキテクチャについて〜](https://qiita.com/s79ns/items/bd8b1f50c34ada016196)
・ [Web API入門#3 〜URIの基礎知識〜](https://qiita.com/s79ns/items/c4ec2db048fa3b13638e)
・ [Web API入門#4 〜クールなURIの設計方法について〜](https://qiita.com/s79ns/items/e2f3b6f66059c2917206)

## TCP/IPの4階層モデル

HTTPは、TCP/IPというネットワークプロトコル（通信規約）がベースとなって作られています。

ネットワークについて学習されていた方であれば、下記の図は見たことがあるかもしれません。
この図は、階層に応じて通信を行う流れを示しており、TCP/IPでは4つの階層に分かれています。
下の階層から簡潔に解説します。

![スクリーンショット 2021-01-13 11.16.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/6303d527-c2c2-90b2-4fab-b1d3306d86ea.png)

#### ネットワーク層
ネットワークエンジニアの方以外では、仕事で触る機会は少ないのかもしれません。
LANケーブルなどの通信機器が該当します。

#### インターネット層

この層に当たるのがIPというプロトコルです。私達がよく耳にするIPアドレスは、データの宛先を示します。
他にパケットなどもこの層で使われています。

#### トランスポート層

TCPというプロトコルを使って、インターネット層で送信したデータに抜け漏れがないかを確認します。
具体的には、接続先のポート番号（入り口）を認識し、コネクションというものを使ってデータの送受信の状態を監視します。

#### アプリケーション層

Webページの表示であれば、HTTPプロトコルが使われ、メールの送信はSMTP（Simple Mail Transfer Protocol）というプロトコルが使われます。用途に応じて使うプロトコルを決めるのがアプリケーション層です。

## HTTPのバージョン

HTTPのバージョンについて表にしました。HTTPは1991年にバージョン0.9で既に登場しています。
年々Webの複雑化に応じて進化しており、長年HTTP1.1が主流でしたが、最近はHTTP2.0が使われ始めました。

それぞれのバージョンで何ができるようになっているのか、上から順に説明します。

| バージョン | 公開年 | 仕様 |
|:--------|-------|:----|
| 0.9     | 1991年 | GETメソッドのみ |
| 1.0     | 1996年 | レスポンスヘッダの追加（ステータスコードなど）、POSTメソッドの追加 |
| 1.1     | 1999年 | 原則、1通信=1リクエスト=1レスポンス |
| 2.0     | 2015年 | ストリーム多重化による複数リクエストの同時通信 |

#### バージョン0.9

バージョン0.9では、情報を取得するGETメソッドのみしか存在していませんでした。

#### バージョン1.0

POSTメソッドの他、レスポンスヘッダが追加されました。
レスポンスヘッダとは、相手にリクエストを要求し、レスポンスを受け取る時の付加情報のようなもので、
通信が成功した時の応答として受け取るステータスコード200などのことです。

#### バージョン1.1

HTTPのバージョンとしては、1.1が長く使われていて1通信につき1リクエスト=1レスポンスが原則でした。

#### バージョン2.0

2015年からは、ストリームの多重化という技術を使うことにより、複数のリクエストを処理でき、かつ高速に表示することができるようになりました。

## HTTP1.1とHTTP2.0との通信の違い

HTTPバージョン1.1と2.0の通信方式の違いを図にしましたのでご紹介します。

![スクリーンショット 2021-01-14 9.12.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/939bf05b-11cd-9daa-113f-2f47d7dcf5ff.png)

図の通りHTTP1.1は、1通信につき1リクエストで1レスポンスなので、ブラウザとサーバー間でやりとりを1つ1つ行わなければいけません。
ですが、HTTP2.0からストリームという仮想トンネルのようなものが使えるようになりました。
イメージとしては、1つの通信でいくつもの仮想トンネルを持っているような感覚で差し支えないと思います。
図では1から2までの通信はHTTP1.1と変わらない通信ですが、3,4のところでストリームを複数作ることによって、同時に2つのリクエストを要求して2つレスポンスが返ってくるという処理となります。
結果、処理を複数同時に行っていますので、リクエストとレスポンスの全体の流れとして時間は短縮されます。

## リクエストとレスポンスの流れ

HTTPにおける、リクエストの流れを図にしました。
これは、Webページを表示する時のリクエストとレスポンスの流れだと思って下さい。

![スクリーンショット 2021-01-13 14.39.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/da7988b5-97b1-101b-ec23-1e503d0c9601.png)

まずリクエストですが、ユーザーがWebページを表示しようとして、ブラウザからURLにアクセスをします。
ブラウザでは、Webページを表示するための情報をまだ持っていないので、情報が欲しいというリクエストデータを作成し、サーバーへ送信をします。（送信後、サーバーから応答があるまで待機します）

そして、ブラウザから送信されたリクエストMSGをサーバーが受信して解析をします。
解析後に、サーバーのリソースにあるHTMLのデータを取得し、取得したHTMLのデータをブラウザに送り返すためのレスポンスMSGを作成して送信します。

サーバーから作成されたレスポンスMSGをブラウザが受信し、レスポンスMSGの内容を解析します。
解析した内容をもとに、Webページとして表示できるようレンダリング処理を行います。

APIでJSONのデータを取得する時でも同じような流れで処理が進みます。

## HTTPメッセージ

リクエストやレスポンスはどういった情報を渡しているのかをご紹介します。

|| リクエスト | レスポンス |
|:-:|:--------|:---------|
| リクエストライン<br>/ステータスライン | メソッド：GET<br>パス：/posts/123<br>プロトコルバージョン：HTTP/2 | プロトコルバージョン：HTTP/2<br>ステータスコード：200<br>テキストフレーズ：OK |
| ヘッダー<br>(メタデータ)    | accept：要求するデータ形式<br>Host：リクエスト先のホスト名<br>User-Agent：リクエスト元の情報 | content-type：返ってくるデータ形式 |
| ボディ<br>(実データ)     | POSTやPUTの時に使う<br>作成したいリソースの情報など | サーバーが返す実際の情報<br>HTMLやJSONなど |

#### リクエストライン

リクエストラインは、プロトコルのバージョンは何で、どんなメソッドを使ってどのパスにリクエストをしているのかが含まれます。ステータスコード200なら成功という意味です。

#### ヘッダー（メタデータ）

ヘッダーは、メタデータという、データのためのデータというものがあります。
ここでいうデータのためのデータとは、acceptやHostなどの実際に欲しい情報の付加情報のことを指します。

#### ボディ（実データ）

ボディは基本的にGETメソッドの時は使わず、POSTメソッドやPUTメソッドの時に使います。
POSTメソッドは、新しくサーバーにデータを作成する時に使われ、作りたいリソースの情報をボディに乗せて
リクエストを送っています。

## httpbinで実際にHTTP通信を確認する

[httpbin](https://httpbin.org)というWebページで、Web APIの動きを確認することができます。

![スクリーンショット 2021-01-14 11.15.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/1114fd5b-1f54-efe3-22fe-26cfc31e2798.png)

① 『HTTP Methods』→『GET』→『Try it out』の順にクリックします。

![スクリーンショット 2021-01-14 13.05.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/8799daa7-f10a-6861-113a-31f56758fd8d.png)

② 『Execute』をクリックします。

![スクリーンショット 2021-01-14 13.11.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/e28e11d7-5950-c292-e0d4-f22c13523b3f.png)

③ 表示されたコマンドをコピーします。

![スクリーンショット 2021-01-14 13.13.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/b8197aba-1ecf-0cd2-8d42-e2372b953a62.png)

④ 皆さんお使いのPCのターミナルでペーストして、最後尾に`-v`を付け加えて実行します。
※ windowsの方はcurlのインストールが必要のようです。
※ 実行する際に、最後尾に`-v`を付け加えると、どういうリクエストを要求し、どういうレスポンスを返しているのか確認することができます。

```terminal:terminal
curl -X GET "https://httpbin.org/get" -H "accept: application/json" -v
```

実行後、数十行に渡りレスポンスが返ってきますが、要点のみお伝えします。

```terminal:terminal
// 一部抜粋・大体上から数えて30行目くらいの場所です
> GET /get HTTP/2
> Host: httpbin.org
> User-Agent: curl/7.64.1
> accept: application/json
```

**リクエスト側**

1行目に、リクエストラインのメソッドとパスとプロトコルのバージョンが書かれています。
2行目以降に、ヘッダーの情報としてHost：httpbin.orgに対して、User-Agent：curlバージョン7.64.1でリクエストをしました。accept：要求したのはjsonのデータです。という情報が書かれています。

```terminal:terminal
< HTTP/2 200 
< date: Thu, 14 Jan 2021 04:24:52 GMT
< content-type: application/json
< content-length: 267
< server: gunicorn/19.9.0
< access-control-allow-origin: *
< access-control-allow-credentials: true
< 
{
  "args": {}, 
  "headers": {
    "Accept": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "curl/7.64.1", 
    "X-Amzn-Trace-Id": "Root=1-5fffc794-4c3a28a35cdad0901cd85096"
  }, 
  "origin": "110.4.217.42", 
  "url": "https://httpbin.org/get"
}
```

**レスポンス側**

上のリクエストメッセージのすぐ下に、このようなレスポンスメッセージが返ってきます。

1行目は、ステータスラインで、プロトコルバージョンと、ステータスコード200が返ってきています。
2行目以降は、ヘッダーのデータで、日付、データの形式、データの長さなどetc...。
{ }の部分はボディとなります。

今回はcurlでWeb APIの動きを確認しましたが、検証ツールのネットワークのタブでも同じことができます。

![スクリーンショット 2021-01-14 14.01.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/772631/8c24dfdc-9d48-449b-b0c9-cf023ce1fe4a.png)

## 次の記事はこちら

[Web API入門#6 〜CRUDとHTTPメソッド〜](https://qiita.com/s79ns/items/9b0f76f4bfdf4140a506)