【初心者向け】WebAPIのことを理解するのに重要なHTTPメソッドを学習(途中)



# はじめに
***Webの成功理由はHTTPメソッドにあり***
WebAPIの動きを理解するため、HTTPメソッドを頭に刻み込みます。

|メソッド|意味|
|---|---|
|GET|リソースの取得|
|POST|子リソースの作成、リソースへのデータの追加、そのほかの処理|
|PUT|リソースの更新、リソースの作成|
|DELETE|リソースの削除|
|HEAD|リソースのヘッダ（メタデータ）の取得|
|OPTIONS|リソースがサポートしているメソッドの取得|

※TRACEとCONNECTメソッドはほとんど使われないそうなので、今回は割愛します。

# 参考書籍
[Webを支える技術　7章 HTTPメソッド](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)

# 本の目次

***第7章 HTTPメソッド***

* 7.1 8つしかないメソッド
* 7.2 HTTPメソッドとCRUD
* 7.3 GETーーーリソースの取得
* 7.4 POSTーーーリソースの作成、追加
	* リソースの更新
	* リソースの作成
	* POSTとPUTの使い分け
* 7.5 PUTーーーリソースの更新、作成
* 7.6 DELETE－－－リソースの削除
* 7.7 HEADーーーリソースのヘッダの削除
* 7.8 OPTIONSーーーリソースがサポートしているメソッドの取得
* 7.9 POSTでPUT/DELETEを代用する方法
	* _methodパラメータ
	* X-HTTP-Method-Override
* 7.10 条件付きリクエスト
* 7.11 べき等性と安全性
	* PUTはべき等
	* べき等性の例
	* DELETEもべき等
	* GETとDELETEもべき等、そのうえ安全
	* GETはどこまで安全か
	* 安全でもべき等でもないPOST
* 7.12 メソッドの誤用
	* GETが安全でなくなる例
	* ほかのメソッドでできることにPOSTを誤用した例
	* PUTがべき等でなくなる例
	* DELETEがべき等でなくなる例
* 7.13 Webの成功理由はHTTPメソッドにあり

# 学習したこと
# HTTPメソッド
>本章ではHTTPのリクエストメッセージを特徴づけるメソッドについて解説いたします。
HTTPメソッドは種類こそ8つと少ないですが、重要な役割を果たしています。本章では、メソッドがたった8つでも大丈夫な理由、そしてそこに隠されたHTTPの設計上の工夫を見ていきます。

## HTTPメソッドの種類は8つ（実際に使うのは6つ）

***HTTPメソッド***

|メソッド|意味|
|---|---|
|GET|リソースの取得|
|POST|子リソースの作成、リソースへのデータの追加、そのほかの処理|
|PUT|リソースの更新、リソースの作成|
|DELETE|リソースの削除|
|HEAD|リソースのヘッダ（メタデータ）の取得|
|OPTIONS|リソースがサポートしているメソッドの取得|

***TRACEとCONNECTはほとんど使われない***

>通常のプログラミング言語の感覚からすると、なぜこんなにもメソッドを限定しているのか、それで大丈夫なのかと不安になることでしょう。しかしメソッドの数をぎりぎりまで削ったからこそ、HTTPが、そしてWebが成功したのです。本章では、ほとんど使われていないTRACEとCONNECTを除いた6つのメソッドについて解説します<

## HTTPメソッドとCRUD

***CRUD（Create / Read / Update / Delete）***

>HTTPメソッドのうちGET,POST,PUT,DELETEは、これら4つで「CRUD」という性質を満たすため、代表的なメソッドと言えます。CRUDとは、create（作成）、Read（読み込み）、Update（更新）、Delete（削除）というデータ操作の基本となる4つの処理のことです。CRUDとHTTPメソッドは表7.2のように対応します。

***CRUDとHTTPメソッドの対応***

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

# GET（リソースの取得）

>GETは指定したURIの情報を取得します。最も利用頻度の高いメソッドで、Webページの取得、画像の取得、映像の取得、フィードの取得など、私たちがブラウザを利用しているときはいつも数多くのGETを発行しています。

## GETの例

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

// リクエストはhttp://example.jp/listに対するGETです。
```

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

[
   {"uri" : "http://example.jp/list/item1"},
   {"uri" : "http://example.jp/list/item2"},
   {"uri" : "http://example.jp/list/item3"},
   {"uri" : "http://example.jp/list/item4"}
]

// リクエストに対して、
// サーバーは指定されたURIに対応するデータをレスポンスとして返しています。
```

# POST（リソースの作成、追加）
# POSTの役割
## 子リソースの関係

>POSTの代表的な機能は、あるリソースに対する子リソースの作成です。
ブログ記事の投稿などの操作で使われます。第12章で解説するAtomPubなど、
POSTをこの目的だけに使うプロトコルも多いです。

## POSTの機能①「子リソース作成」

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

こんにちは！
// http://example.jp/listに対して新しい子リソースを作成するようにPOSTで指示
// POSTのボディには、新しく作成するリソースの内容を入れる
```

```レスポンス
HTTP/1.1 201 Created                     // ｽﾃｰﾀｽｺｰﾄﾞ201は新しいリソースが生成されたことを示す
Content-Type: text/plain; charset=utf-8  
Location: http://example.jp/list/item5     //Locationヘッダに新しいリソースのURIが入ってる
                                                                     つまり、listの下に、新たに/list/item5というリソース(子リソース)を生成
こんにちは！
```

## POSTの機能②「リソースへのデータの追加」

>子リソースの作成ほど一般的ではありませんが、POSTの代表的な機能の2つめは既存リソースへのデータの追加です。

>例としてログリソースを考えてみましょう。まずはリソースをGETしてみます。

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

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

2010-10-10T10:10:00Z, GET /list, 200
2010-10-10T10:11:00Z, POST /list, 201
2010-10-10T10:20:00Z, GET /list, 200
```

>このリソースのURIはhttp://example.jp/logで、CSV形式のログを表現します。
　このリソースに新しいログを追加するにはPOSTを使います。

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

2010-10-10T10:13:00Z, GET /log, 200
```

```レスポンス
HTTP/1.1 200 OK　　//　ｽﾃｰﾀｽｺｰﾄﾞ200は、データの追加を意味する。
```

>データ追加としてPOSTしたときに、そのデータをリソースの末尾に追加するのか
先頭に追加するのかはサーバ側の実装に依存します。また、そもそもあるリソースへの
POSTが作成を意味するのかデータ追加を意味するのかも実装に依存します。URIを見ただけでは
POSTの挙動はわかりません。POSTの挙動はWebサービスやWebAPIの仕様書などで表現します

## POSTの機能③「ほかのメソッドでは対応できない処理」
## 例：「検索キーワードが極端に長かった」場合、どうするのか？

>POSTの3つめの機能は、ほかのメソッドでは対応できない処理の実行です。
検索結果を表現する次のURIを例に考えてみましょう。

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

>通常はこのURIをGETすることで検索を実行しますが、キーワードが非常に長かった場合はどうなるのでしょうか。
URIの長さはキーワードに連動します。第4章で述べたとおり、URIの仕様上は長さ制限がありませんが、
実装上は2000文字などの上限が存在します。そのような長いキーワードの場合、URIにキーワードを入れて
GETする方式は利用できません。この場合、以下のようにPOSTを用います。

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

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

// GETではURIに含めていたキーワードを、POSTではリクエストボディに入れられます。
// これによってどんなに長いキーワードでも実現できます。
```

# PUT （リソースの更新、作成）
# PUTの機能①「リソースの更新」

>PUTの1つめの機能はリソースの更新です。
まずは先ほどPOSTで作成したitem5をGETするところから始めましょう。

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

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

こんにちは！
```

>次にこのリソースをPUTを使って「こんにちは！」から「こんばんは！」に変換してみます

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

こんばんは！
```

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

こんばんは！
```

>この例ではPUTへのレスポンスにリソースを更新した結果の表現が入っています。PUTへのレスポンスは、この例のようにボディに結果を入れてもよいですし、ボディには何も入れずに、レスポンスがボディを持たないことを示す***204 No Content***を返してもかまいません。

# PUTの機能②「リソースの作成」

>PUTの2つめの機能はリソースの作成です。
たとえばhttp://example.jp/newitemがまだ存在しないとします。

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

新しいリソース/newitemの内容
```

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

新しいリソース/newitemの内容
```

>このPUTは存在しないURIへのリクエストのため、サーバはリソースを新しく作成すると解釈し、リクエストが成功した場合は***201 Created***を返します。POSTの場合は新しく作成したリソースのURIがLocationヘッダで返りましたが、PUTの場合はすでにリソースのURIを知っているためLocationヘッダを返す必要はありません。
/newitemがすでに存在していた場合は、先述したリソースの更新処理になります。

# POSTとPUTの使い分け
## POSTとPUTをどのように使い分ければいいか？
***正解は存在しないが・・***

* 設計上の指針として次の事実がある
	* `POST`リソースを作成する場合、リソースのURIの決定は`サーバ側`にある
	* `PUT`でリソースを作成する場合、リソースのURIは`クライアント`が決定する

## （一般的には）サービスの特徴によって、使い分ける
* TwitterのようにつぶやきのURIをサーバ側で自動的に決定するWebサービスの場合は、POSTを用いるのが一般的。
* 逆にWikiのようにクライアントが決めたタイトルがそのままURIになるWebサービスの場合は、PUTを使うほうが適している。

>ただし、PUTの場合、リソースの上書きを避けるためにクライアントで事前にURIの存在をチェックしなければならないかもしれません。

## （特に理由がなければ）POSTがベター

***技術的な負担を軽減するならPOST***
>一般的に、クライアントがリソースのURIを決定できるということは、クライアントを作るプログラマーがサーバの内部実装（URIにどの文字を許すのか、長さの制限はどれくらいかなど）を熟知していなければなりません。そのため、PUTのほうがどうしてもサーバーとの結合が密になります。***特別な理由がない限りは、リソースの作成はPOSTで行いURIもサーバ側で決定する***、という設計が望ましいでしょう。

# DELETE（リソースの削除）

>Deleteはその名のとおり、リソースを削除するメソッドです。

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

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

# HEAD（リソースのヘッダの取得）

>HEADはGETによく似たメソッドです。GETはリソースを取得するメソッドですが、HEADはリソースのヘッダ（メタデータ）だけを取得するメソッドです。

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

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

>HEADへのレスポンスにはボディが含まれません。この性質を利用すると、ネットワークの帯域を節約しながらリソースの大きさを調べたり、リソースの更新日時を取得したりできます。

# OPTIONS 「リソースがサポートしているメソッドの取得」

>最後のメソッドはOPTIONSです。OPTIONSはそのリソースがサポートしているメソッドの一覧を返します。次の2つの例を見てください。

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

```レスポンス
HTTP/1.1 200 OK
Allow: GET,HEAD, POST     //そのリソースが許可するメソッド一覧
```

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

```レスポンス
HTTP/1.1 200 OK
Allow: GET,HEAD,PUT, DELETE　  //そのリソースが許可するメソッド一覧
```

>OPTIONSを実装する場合、多くのWebアプリケーションフレームワークでは、リソースごとに対応しているメソッドを返すように自前で実装しなければなりません。ApacheのようなWebDAVに対応したWebサーバでは、設定ファイルでOPTIONSの挙動を設定できます。

# POSTでPUT/DELETEを代用する方法

***現実に一番よく利用されるHTTPメソッドはGETとPOSTの2つ***

>これまで説明してきたGET、POST、PUT、DELETE、HEAD、OPTIONSの6つが主なHTTPメソッドです。しかし、現実に一番よく利用されているのはGETとPOSTの2つです。これはHTMLのフォームで指定できるメソッドがGETとPOSTだけという制限に起因します。

```フォームにGETを指定した例
<form method="GET" action="/list">
	・・・
</form>
```

```フォームにPOSTを指定した例
<form method="POST" action="/list">
	・・・
</form>
```

***Ajaxの発展で任意のメソッドを発行できるように***

>HTMLのこの制限により、WebアプリケーションではGETとPOSTだけを利用する時代が長年続きました。しかし、この制限はAjaxの発展とともに解消されつつあります。Ajaxで用いるXMLHttpRequestというモジュールを利用すると、任意のメソッドを発行できるからです。

>ただし、それでもGETとPOSTだけを使わなければならない状況も存在します。たとえばXMLHttpRequestをサポートしない携帯電話向けブラウザはフォームしか利用できませんので、GETとPOST以外使えません。また、セキュリティ上の理由から、プロキシサーバーでGETとPOST以外のアクセスを制限している場合もあります。このような状況でサーバーにPUTやDELETEを伝える手法が2つあります。

## _methodパラメータ

>1つめは_methodパラメータを用いる方法です。フォームの隠しパラメータ(hidden)に_methodというパラメータを用意し、そこに本来送りたかったメソッドの名前を入れます。_methodパラメータはRuby on Railsが採用しています。

>たとえば次のフォームがあったりします。

```
<form method="POST" action="/list/item1">
	<input type="hidden" id="_method" name="_method" value="PUT"/>
	<textarea id="body">...</textarea>
</form>
```

>このフォームを送信すると、次のリクエストが送られるでしょう。

```
POST /list/item1 HTTP/1.1
Host: example.jp
Content-Type: application/x-www-form-urlencoded

_method=PUT&body=...
```

>ボディには、フォームで入力した項目をURIのクエリパラメータと同じ仕様でエンコードした（idと値を「=」でつないで「&」で連結した）テキストが入っています。Content-Typeヘッダの値application/x-www-form-urlencodedは、このフォーマットを表すメディアタイプです。Webアプリケーションフレームワークなどのサーバー側の実装は、_methodパラメータを見て、このリクエスト自体をPUTとして扱います。

## X-HTTP-Method-Override

>_methodパラメータはフォームを利用してリクエストを送る場合は有効な手法ですが、POSTの内容がXMLなど、application/x-www-form-urlencoded以外の場合は利用できません。このような場合に利用できるのがX-HTTP-Method-Overrideヘッダです。こちらはGoogleのGData(Google Data Protocol)が採用している手法です。

```
POST /list/item1 HTTP/1.1
Host: example.jp
Content-Type: application/xml; charset=utd-8
X-HTTP-Method-Override: PUT

<body>...</body>
```

>Webアプリケーションフレームワークなどのサーバ側の実装は、X-HTTP-Method-Overrideヘッダを見て、このリクエストをPUTとして扱います。