HTTPメソッド~GETとPOST時々PUT with DELETE~

# HTTPメソッド
HTTP1.1には8つのメソッドが定義されています。

| メソッド　        | 意味　　　　　　　　　　　　　　　　　　 |
|:-----------------|:-------------------------------------|
| GET              | リソースの取得　　　　　　　　　　　　　 |
| POST             | 子リソースの作成等　　　　　　　　　　　 |
| PUT              | リソースの更新・作成　　　　　　　　　　 |
| DELETE           | リソースの削除　　　　　　　　　　　　　 |
| HEAD             | リソースのヘッダの取得　　　　　　　　　 |
| OPTIONS          | リソースがサポートしているメソッドの取得 |
| TRACE            | 自分にリクエストを返す　　　　　　　　　 |
| CONNECT          | プロキシ動作のトンネル接続への変更　　　 |

このうち、GET, POST, PUT, DELETEは「CRUD」という性質を満たすので、代表的かつよく使われるメソッドです。

| CRUD名　  | メソッド         | 意味           |
|:---------|:-----------------|:--------------|
| Create   | POST             | 作成　　　　　　|
| Read     | GET              | 読み込み　　　　|
| Update   | PUT              | 更新　　　　　　|
| Delete   | DELETE           | 削除　　　　　　|

## GET
GETは指定したURIの情報を取得します。

```:リクエスト
GET /user HTTP/1.1
Host: hoge.com
```
```:レスポンス
HTTP/1.1 200 OK
Content-Type: application/json

[
 {"url": "http://hoge.com/user/1"},
 {"url": "http://hoge.com/user/2"}
]
```
http://hoge.com/user にGETリクエストを送ると、json形式のデータが返ってきている様子です。リソースの取得が成功しているのでステータスコード200となっています。
もちろん、json形式以外にもhtmlなど様々な形式でレスポンスを返すことができます。

## POST
POSTは主に子リソースの作成で使われますが、GETやDELETEの代替など様々なことができる万能君です。

### 子リソースの作成
まずは子リソースの作成を見てみます。

```:リクエスト
POST /user HTTP/1.1
Host: hoge.com
Content-Type: appliation/json

{
 "user": "tama"
}
```
```:レスポンス
HTTP/1.1 201 Created
Content-Type: application/json
Location: http://hoge.com/user/3

{
 "user": "tama"
}
```
/user に対してPOSTすることで、/user/3という子リソースを作成することができました。ステータスコードは201です。
ここで重要なのがリクエストを送る側が/user/3というURIを指定しているわけではなく、サーバー側が/user/3というURIを作成しているという点です。
あとで出てくるPUTとの違いとなっています。

### ほかのメソッドで対応できない処理
たとえば検索結果を取得するURIを次のようにしたとします。

```
http://hoge.com/search?q={keyword}
```
keywordにはユーザーが入力した検索キーワードや条件が入ります。
もしここのkeywordに5000字ほどの長さが入るとしたらどうでしょうか。URIの仕様上は長さの制限はありませんが、実装上は2000文字などの上限が存在します。
URIで表現できなければGETを使用することができません。そのような場合にPOSTを使用します。

```:リクエスト
POST /search HTTP/1.1
Content-Type: application/x-www-form-urlencoded

q=hoge+fuga+moga+..............
```
このようにボディに含めることでGETの代替として使うことができます。

## PUT
PUTはリソースの更新やリソースの作成を行えます。

### リソースの更新
POSTで作成した/user/3を更新してみたいと思います。

```:リソース
{
 "user": "tama"
}
```

```:リクエスト
PUT /user/3 HTTP/1.1
Host: hoge.com
Content-Type: application/json

{
 "user": "tamatama"
}
```

```:レスポンス
HTTP/1.1 200 OK
Content-Type: application/json

{
 "user": "tamatama"
}
```
/user/3のユーザー情報を"tama"から"tamatama"に変更することに成功しました！

### リソースの作成
こんどは/user/4のリソースを作成してみます。

```:リクエスト
PUT /user/4 HTTP/1.1
Host: hoge.com
Content-Type: application/json

{
 "user": "Bob"
}
```

```:レスポンス
HTTP/1.1 201 Created
Content-Type: application/json

{
 "user": "Bob"
}
```
これで/user/4というリソースを作成することができました！
POSTと違う点はリクエストを送る側がURIを指定しているところです。そのためPUTのレスポンスにはLocationが含まれていません。(クライアント側はすでにURIを知っているのでわざわざ教える必要がない。)

POSTとPUTの使い分けについては後述します。

## DELETE
DELETEはリソースの削除に使います。

```:リクエスト
DELETE /user/4 HTTP/1.1
Host: hoge.com
```

```:レスポンス
HTTP/1.1 200 OK
```
これで/user/4のBobを削除することに成功しました！
リソースが削除されているので基本的にレスポンスはボディを持ちません。なので、204 No Content というボディがないことを表すステータスコードが使われることがあります。

## POSTとPUT
リソースの作成はPOSTでもPUTでもできるのでどちらを使えばよいか迷いますよね？
POSTとPUTの違いはURIをどちらが決めるかという点です。
POSTはサーバー側がURIを決めるので、サーバー側がURIを決定したいときに使います。
PUTはクライアント側がURIを決めるので、たとえば、ブログなどの投稿でタイトルをURIにしたい場合などはPUTの方がよいかもしれません。
ただPOSTを使うかPUTを使うかの正解はないので、リソースの作成はPOST、リソースの更新はPUTといったシンプルな設計にすることも一つの手かもしれません。 

## べき等性と安全性
べき等性とは「ある操作を何回行っても結果が同じこと」です。
HTTPメソッドのGETでいうと、/user/1のレスポンスが岡村君の情報なら、/user/1に何回でもGETリクエストを送ってもレスポンスが岡村君の情報という同じ結果が返ってきます。


安全性とは「操作対象のリソースの状態を変化させないこと」です。
PUTメソッドはリソースの更新(リソースの状態を変更させる)ので安全ではありません。

| メソッド　        | 性質　　　　　　　　　　　　　　　　　　 |
|:-----------------|:-------------------------------------|
| GET              | べき等かつ安全　　　　　　　　　　　　　 |
| POST             | べき等でも安全でもない　　　　　　　　　|
| PUT              | べき等だが安全でない　　　　　　　　　　 |
| DELETE           | べき等だが安全でない　　　　　　　　　　|

ただし、メソッドを誤用したり設計が誤っている場合、GETが安全でなくなったり、PUTがべき等でなくなったりしてしまいます。
このような場合は設計などを見直してみましょう。

### PUTがべき等でなくなる例
トマトの値段を表すリソースhttp://hoge.com/tomato があるとします。
トマトの値段を100円から200円に更新してみましょう。

```:リクエスト
PUT /tomato HTTP/1.1
Host: hoge.com
Content-Type: text/plain

+100
```

```:レスポンス
HTTP/1.1 200 OK
Content-Type: text/plain

200
```
無事にトマトの値段を200円に更新することができました！
ここでPUTはべき等なので同じリクエストを送ると同じリクエストが返ってくるはずです。

```:リクエスト
PUT /tomato HTTP/1.1
Host: hoge.com
Content-Type: text/plain

+100
```

```:レスポンス
HTTP/1.1 200 OK
Content-Type: text/plain

300
```

あれ？さきほどのレスポンスと違うレスポンスが返ってきてしまいました。これではPUTはべき等であるといえません。

今回の場合の誤りは200円と直接指定せず、+100円と指定したことです。リクエストを200にしておけば何度リクエストを送っても同じ200というレスポンスが返ってきます。(べき等である。)


[Webを支える技術 HTTP,URI,HTML,そしてREST](https://www.amazon.co.jp/Web%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93-HTTP%E3%80%81URI%E3%80%81HTML%E3%80%81%E3%81%9D%E3%81%97%E3%81%A6REST-WEB-PRESS-plus/dp/4774142042/ref=sr_1_1?adgrpid=52846719243&gclid=Cj0KCQjw9JzoBRDjARIsAGcdIDVXq0-jeLOZQy5iSimbrn76n-bH4dC76iOlLXn4XOXkenzWeB--r7saAj0IEALw_wcB&hvadid=338558549746&hvdev=c&hvlocphy=1009300&hvnetw=g&hvpos=1t1&hvqmt=e&hvrand=10098567977622848698&hvtargid=kwd-333749887651&hydadcr=16039_11170864&jp-ad-ap=0&keywords=web%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93&qid=1560829886&s=gateway&sr=8-1)