改めてHTTPを学ぶ

# はじめに
### この記事は？
改めてHTTPについて学んだことをまとめた記事。

### 対象者
仕事でなんとなくHTTPに触れているが、いざ「HTTPってなに？」と聞かれると答えにつまる人


# HTTPとは
Hypertext Transfer Protocolの略。

## Hypertextってなに？
**Hypertext**とは、複数の文書(テキスト)を相互に参照できる仕組み。
「テキストを超える」という意味から"hyper"(〜を超えた)"text"(文書)と名付けられた。

文書間の参照は、**Hyperlink**という、コンピュータに理解できる形式で記述されており、瞬時に参照先の文章を閲覧できる。

最も有名なHypertextの実装は**World Wide Web**である。ネットワーク上でリンクされたHyperlinkのつながりが、あたかも蜘蛛の巣のように見えることから、この名(世界に広がる蜘蛛の巣)がついた。

また、Hypertextを記述するためのマークアップ言語の1つとして**HTML(Hypertext Markup Language)**がある。

## Transferってなに？
対象をある場所から別の場所へ送ること。

## Protocolってなに？
(情報工学分野では)マシンやソフトウェア同士のやりとりに関する取り決め。

## つまりHTTPとは？
Hypertextをマシンやソフトウェア間でやりとりする上での取り決め。


# どんな取り決め？
登場人物は**クライアント**と**サーバー**の2つ。
クライアントがサーバーへ**リクエスト**を送り、サーバーはそれを受けてクライアントへ**レスポンス**を返す。

例えば`www.google.co.jp`へ`GET`リクエストを送ったとすると

```
$ curl -v www.google.co.jp 
```

## **リクエスト**

```
> GET / HTTP/1.1          # リクエストライン
> Host: www.google.co.jp  # ここからヘッダ
> User-Agent: curl/7.54.0
> Accept: */*             # ここまでヘッダ
                          # 以下ボディが続く場合もある
```
### **1. リクエストライン**
この部分

```
GET / HTTP/1.1
```

HTTPリクエストで一番重要な部分。
**HTTPメソッド**(`GET`)、**URI**(`/`)、**HTTPバージョン**(`HTTP/1.1`)から成り立つ。

HTTP1.1ではメソッドは8つ定義されているが、その中で主に使うのは以下の4つ。

| メソッド  | 意味         |
|:-------|:------------------|
| **GET**    | リソースの取得        |
| **POST**   | 子リソースの作成、リソースへのデータの追加、そのほかの処理|
| **PUT**    | リソースの更新、リソースの作成| 
| **DELETE** |  リソースの削除       | 

HTTP1.1の場合、リクエストURIの形式はパス(`/`)でも絶対URI(`www.google.co.jp`)でもよい。


### **2. リクエストヘッダ**

この部分

```
> Host: www.google.co.jp
> User-Agent: curl/7.54.0
> Accept: */* 
```
各ヘッダは「**名前:値**」という構成をしている。
**Hostヘッダは必須。**
いろんなヘッダがある。

| ヘッダ名 | 意味   |例 |
|:-------|:------|:-------|
|**Host**| 必須。リクエストの送信先ホスト名やポート番号を指定する| `www.google.co.jp` |
|**Accept**|クライアントが受け取ることのできるデータの種類(MIMEタイプ)| text/html, application/json |
|**Accept-Language**| クライアントが受け取ることのできる自然言語の種類| ja-JP, en-gb, fr|
|**User-Agent**|クライアントの情報。アプリケーション名、バージョン、ホストOSなど|Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1C28 Safari/419.3|
|**APIKey**|APIアクセス時の認証に必要なキー|APIによる|
|**Authorization**|認証・認可の種類とcredential|Basic YWxhZGRpbjpvcGVuc2VzYW1l, Bearer mF_9.B5f-4.1JqM|

ほかにも色々ある。
こちらに一覧。
https://developer.mozilla.org/ja/docs/Web/HTTP/Headers

### **3. リクエストボディ**
リソースを新しく作成したり更新したりするときは、ここにその情報を入れることもある。
リクエストボディがつくのは`POST`の場合が多い。
JSONデータやパラメータを持たせる場合は、リクエストボディに表現される。

例えば以下のような。

```
{
	title: "test",
	content: "testtesttesttesttest"
}
```


## **レスポンス**
```
< HTTP/1.1 200 OK                     # ステータスライン
< Date: Sun, 18 Feb 2018 01:06:16 GMT # 以下レスポンスヘッダ
< Expires: -1
< Cache-Control: private, max-age=0
< Content-Type: text/html; charset=Shift_JIS
< P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."
< Server: gws
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
< Set-Cookie: 1P_JAR=2018-02-18-01; expires=Tue, 20-Mar-2018 01:06:16 GMT; path=/; domain=.google.co.jp
< Set-Cookie: NID=124=lXLnbtWpi0pyPq1YkzvcikNyJ8KGh5N-1HLqY0n-yeTX2_GdooMqeyKRQ6HeoVTUcS9ZqvoZQkKxbPntXEurfeUsl06zpa6HwI0F8dZW5JVLOqHNLt0bnqiLAHWGbg9a; expires=Mon, 20-Aug-2018 01:06:16 GMT; path=/; domain=.google.co.jp; HttpOnly
< Accept-Ranges: none
< Vary: Accept-Encoding
< Transfer-Encoding: chunked          # ここまでレスポンスヘッダ
<                            
<!doctype html><html itemscope=""...  # 以下レスポンスボディ
                                      # 以下省略
```

### **1. ステータスライン**
この部分

```
HTTP/1.1 200 OK 
```
リクエスト同様、レスポンスでもこの1行目が最も重要。
**HTTPバージョン**(`HTTP/1.1`)、**ステータスコード**(`200`)、**レスポンスフレーズ**(`OK`)から成る。

ステータスコードには以下のようなカテゴリが存在する。

|ステータスコード|意味|説明|
|:-----------|---|---|
|**1xx**| Informational(情報)|リクエストの処理が継続していることを表す|
|**2xx**| Success(成功)|リクエストが成功したことを表す|
|**3xx**|Redirection(リダイレクション)|リクエストを完了させるには、さらに動作が必要であることを表す|
|**4xx**|Client Error(クライアントエラー)|クライアント側に起因するエラーのため、リクエストが失敗したことを表す|
|**5xx**|Server Error(サーバーエラー)|サーバー側に起因するエラーのため、リクエストが失敗したことを表す|


なかでもよく登場するのがこちらなので、まずはこれを知っておけばよい。

|ステータスコード|意味|説明|
|:--|:--|:--|
|**200**|OK|リクエストが正常に完了したことを表す|
|**302**|Found|リクエストされたリソースが別のURIに属していることを表す。リダイレクトで利用される|
|**401**|Unauthorized|ユーザ認証に失敗したことを表す|
|**403**|Forbidden|アクセス権限がないため、サーバにリクエストの実行を拒否されたことを表す|
|**404**|Not Found|リクエストURIに一致するリソースを見つけられなかったことを表す。|
|**500**|Internal Server Error|サーバ内部のプログラム実行においてエラーが発生したことを表す|


### **2. レスポンスヘッダ**
レスポンスの2行目から空行まで。
この部分。

```
< Date: Sun, 18 Feb 2018 01:06:16 GMT # 以下レスポンスヘッダ
< Expires: -1
< Cache-Control: private, max-age=0
< Content-Type: text/html; charset=Shift_JIS
< P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."
< Server: gws
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
< Set-Cookie: 1P_JAR=2018-02-18-01; expires=Tue, 20-Mar-2018 01:06:16 GMT; path=/; domain=.google.co.jp
< Set-Cookie: NID=124=lXLnbtWpi0pyPq1YkzvcikNyJ8KGh5N-1HLqY0n-yeTX2_GdooMqeyKRQ6HeoVTUcS9ZqvoZQkKxbPntXEurfeUsl06zpa6HwI0F8dZW5JVLOqHNLt0bnqiLAHWGbg9a; expires=Mon, 20-Aug-2018 01:06:16 GMT; path=/; domain=.google.co.jp; HttpOnly
< Accept-Ranges: none
< Vary: Accept-Encoding
< Transfer-Encoding: chunked 
```


### **3. レスポンスボディ**
この部分

```
<!doctype html><html itemscope="" # 以下省略
```
今回の場合はリクエスト時にHTML形式を要求しているため、HTMLデータが入っている。
ブラウザを使用している場合はブラウザがそのHTMLデータを解釈して描画する。

JSONをやりとりするAPIなどの場合は、ここにJSONデータが入ってくる。


### 参考にしたもの
- [本:『Webを支える技術』](https://www.amazon.co.jp/dp/4774142042)
- [本:『プロになるためのWeb技術入門』](https://www.amazon.co.jp/dp/4774142352)
- [Wikipedia: データ転送](https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%BC%E3%82%BF%E8%BB%A2%E9%80%81)
- [Wikipedia: プロトコル](https://ja.wikipedia.org/wiki/%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB)