HTTPを理解する③ HTTPメソッドとは

## HTTPメソッド
HTTPリクエストを用いてwebサーバーに具体的な要求をしているのはHTTPリクエスト内に含まれるHTTPメソッドです。このメソッドは全部で８つあります。主に使われるのはTRACEとCONNECTを除いた６つです。そのなかでも基本となるCRUDの性質を満たすGET、POST、PUT、DELETEについて紹介します。

| HTTPメソッド名 | 説明 |
|:-:|:-:|
| HEAD  | HTTPヘッダー(メタデータ)の情報のみを取得する。データの更新日時やデータのサイズを取得したいときに使用する。  |
|  GET | HTMLファイルや画像といったデータを取得する際に使用される。webサイト閲覧時には一番使われる。  |
| POST  | データの追加や子リソースの作成。  |
| PUT | データを更新する際に使われる。  |
|  DELETE | データの削除に使用される。  |
| CONNECT  |  webサーバーに接続する前に別サーバー(プロキシ)を中継して接続する際に使用される。 |
| OPTIONS  | 利用できるHTTPメソッドを知りたいときに使用する。  |
| TRACE  | webブラウザとwebサーバーの経路をチェックする際に使う。  |

## HTTPメソッドとCRUD
HTTPメソッドのうちGET、POST、PUT、DELETEの四つは「CRUD」という性質を満たすためHTTPメソッドの中でも代表的なメソッドです。CRUDというのはCreate(作成)、Read(読み込み)、Update(更新)、Delete(削除)といったデータを操作する上で基本となる処理のことです。

## GETメソッド
指定したURIの情報を取得します。
一番よく使われ、webページ、画像、映像、音声、フィードといった普段ブラウザで使用するようなものはだいたいGETメソッドを使用しています。

```リクエスト.
GET /list HTTP/1.1
Host: example.jp
```

```レスポンス.
HTTP/1.1 200 OK
Content-Type: application/json
[
 {"uri": "http://example.jp/list/item1"}
]
```

このリクエストはhttp://example.jp/list/item1に対するものです。サーバーはリクエストに対してURIに対応するデータをレスポンスとして返します。

## POSTメソッド
データをwebサーバーに対して送信する際に使用されます。実際は３つの役割を持ち、二番目に使用される頻度が高いメソッドです。

### 子リソースの作成
POSTの代表的な機能としてあるリソース(データのこと)に対する子リソースの作成です。

```リクエスト.
POST /list HTTP/1.1
Content-Type: text/plain; charset=utf-8

筆箱！
```

```レスポンス.
HTTP/1.1 201 Created
Content-Type: text/plain; charset=utf-8
Location: http://example.jp/list/item5

筆箱！
```

このリクエストではhttp://example.jp/list に対して新しい子リソースを作成するようにPOSTで指示しています。POSTのボディに新しく作成するリソースの内容が入っています。レスポンスで201 Createdというステータスコードが返ってきているため、新しいリソースが生成されていることが分かります。
http://example.jp/list/item5 の「list/item5」部分よりlist下に「item5」というリソースができたことがわかります。

### リソースへのデータの追加
既存リソースへのデータの追加も機能の一つです。

```リクエスト.
POST /log HTTP/1.1
Host: example.jp

2018-05-11T11:33:11Z, GET /log, 200
```

```レスポンス.
HTTP/1.1 200 OK
```

この場合だと新しいログを追加しています。結果としてレスポンスが「200 OK」が返ってきています。リクエストが新規リソース作成ではなくデータの追加を意味しています。

### 他のメソッドでは対応できない処理
他のメソッドでは対応できない処理を代行してくれます。
いかに検索結果を表示するURIを見てみましょう。

```
http://example.jp/search?q={検索キーワード}
```

通常はこのURIをGETすることで検索を実行しますが、仮に検索ワードの部分がとても長かった場合、GETは使用できなくなってしまいます。(URIの仕様で2000文字までが上限)

```
POST /search HTTP/1.1
Content-Type: application/x-www-form-urlencoded

q=very+long+keyword+foo+bar+...+....
```

そこでGETではURIに含めていたキーワードをPOSTではリクエストボディにいれることで、どんなに長いキーワードでも実現できるようになりました。

## PUTメソッド
リソースの内容の更新と、リソースの作成です。

### リソースの更新
まずは更新前にリソースをGETします、その後PUTを使ってリソースを更新します。

```リクエスト.
PUT /list/item5 HTTP/1.1
Host: example.jp

更新されたよ！
```

```レスポンス.
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8

更新されたよ！
```

「200 OK」が返ってきて更新に成功しています。この例ではボディ部分に結果が入っていますが、ボディに何も入れずにレスポンスがボディを持たない「204 No Content」 が返ってくることもあります。

### リソースの作成
POSTもリソースの作成ができますが、PUTでもできます。
「http://example.jp/newitem 」がまだ存在していないとします。

```リクエスト.
PUT /newitem HTTP/1.1
Host: example.jp
Content-Type: text/plain; charset=utf-8

新しいリソースの作成
```

```レスポンス.
HTTP/1.1 201 Created
Content-Type: text/plain; charset=utf-8

新しいリソースの作成
``

このPUTは存在していないリソースのURIにリクエストをとなり、サーバーはこれをリソースを新しく作成すると判断し、レスポンスとして「201 Created」が返ってきます。

### DELETEメソッド
リソースを削除するメソッドです

```リクエスト.
DELETE /list/item2 HTTP/1.1
Host: example.jp
```

```レスポンス.
HTTP/1.1 200 OK
```

DELETEメソッドのレスポンスはボディもたないため、「204 No Content」が使われることもあります。

## GETとPOSTの違い
GETメソッドでもPOSTメソッドと同じようにデータを送信することができます。しかしGETメソッドを使用してデータを送信する場合、URLの後ろにデータが組み込まれるため、webブラウザの閲覧履歴にURLが残ってしまいます。これはセキュリティー上よくありません。

```GETメソッド.
GET/login.html?name=sample&pass=password
```

ですがPOSTメソッドでデータを送信した場合、HTTPリクエスト内のメッセージボディにデータが組み込まれるため、閲覧履歴に残ることがありません。

## POSTとPUTの違い
POSTメソッドでもPUTメソッドでもリソースを作成できてしまうことがわかりました。ではこの二つはどう使い分けていけばいいのでしょうか？それはリソースを作成したときのURIの違いにあります。POSTメソッドでリソースを作成する場合、クライアント(サービスだとサービスを使っている人、もしくは客)側がURIを指定して作成することはできません。この時のURIの決定権はサーバー側にあります。逆にPUTでリソースを作成する場合、URIはクライアントが決定します。
これらから、リソースを作成する場合はPOSTメソッドを用いて、サーバー側がURIを決定するほうが望ましいでしょう。PUTメソッドではクライアント側がサーバーの内部事情を熟知した上で、URIを決定しないといけなくなります。