読書研修ーWebを支える技術　第７章HTTPメソッド

## 8つしかないメソッド
HTTPメソッドには、クライアントか行いたい処理をサーバに伝えるという重要な任務があります。
|メソッド | 意味	 |
|:-:|:-:|
| GET | リソースの取得  |
| POST|  子リソースの作成、リソースへのデータの追加、そのほかの処理 |
| PUT |  リソースの更新、リソースの作成 |
| DELETE |  リソースの削除 |
|  HEAD |  リソースのへッダ(メタデータだけ)の取得 |
|  OPTIONS | リソースがサポートしているメソッドの取得  |
| TRACE  |  自分宛にリクエストメッセ-ジを返す(ループバック)試験	 |
|  CONNECT | プロキシ動作のトンネル接続への変更  |

#### CRUD性質：Create、Read、Update、Delete

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

## POSTとPUTの使い分け
リソースの作成
| メソッド| URI決定権 |
|:-:|:-:|
| POST  |  サーバ側にある |
|  PUT |  クライアントにある |

一般的リソースの作成はPOSTで行いURIもサーバ側で決定する。

## OPTIONS　リソースがサポートしているメソッドの取得 
~~~
リクエスト
OPTIONS /list HTTP/2
Host:example.jp

レスポンス
HTTP/2 200 OK
Allow:GET,HEAD,POST
~~~
レスポンスに含まれるAllowヘッダは、そのリソースが許可するメソッドの一覧です。
OPTIONS自体はAllowヘッダには含めない。

OPTIONSを実装する場合、多くのWebアプリケーションフレームッークでは、リソ-スごとに対応しているメソッドを返すように自前で実装なければなりません。


### POSTでPUT/DELETEを代用する方法
現実に一番よく利用されているのはGETとPOSTの2つです。
これはHTMLのフオームで指定できるメソッドがGETとPOSTだけという制限に起因します。
~~~
フオームにGETを指定した例
<form method="GET" action="/list">...</form>
フオームにPOSTを指定した例
<form method="POST" action="/list">...</form>
~~~

HTMLのこの制限により、WebアプリケーションではGETとPOSTだけを利用する時代が長年続きました。
セキュリティ上の理由から、プロキシサーバでGET とPOST 以外のアクセスを制限している場合もあります。

#### ２つの代用する方法
|方法名 | 方法 | 誰採用 | だめの場合 |
|:-:|:--|:--|:--|
|  _methodパラメータ |  フオームの隠しパラメータ(hidden)に_methodというパラメータを用意し、そこに本来送りたかったメソッドの名前を入れ ,このリクエスト自体をPUTとして扱う|  Ruby on Rails | POSTの内容かXMLなど、application/x-www-form.urlencoded以外の場合  |
|  X-HTTP-Method-Override  |  このリクエスト自体をPUTとして扱う |  GoogleのGData(Google Data Protocol) |   |

#### _methodパラメータ
~~~
<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=...
~~~

####  X-HTTP-Method-Override 
~~~
POST /list/item1 HTTP/1.1 Host:example.jp
Content-Type:application/xml; charset=utf-8 X-HTTP-Method-Override: PUT
<body>...</body>
~~~

## 条件付きリクエスト
Conditional Request
HTTPメソッドと更新日時などのへッダを組み合わせることで、メソッドを実行するかどうかを、リソ-スの更新日時を条件にサ-バか選択できるようになります。
## べき等性と安全性
### べき等とは
「ある操作を何回行っても結果が同じこと」を意味する数学用語です。
### 安全とは
「操作対象のリソースの状態を変化させないこと」
たとえば GETには副作用がないので、GETを同じリソースに何回発行してもリソースの状態は変化しません。

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

## メソッドの誤用
Web サービスやWeb APIの設計を誤ると、これらのメソッドが安全でなくなったり、べき等でなくなったりする可能性があります。
### GETが安全でなくなる例
GETの目的はリソースの取得です。しかし、誤った目的でGETを利用している Web APIを無視できない割合で見かけます。
~~~
GET /resources/1/delete HTTP/1.1 
Host: example.jp
~~~
http://example.jp/resources/1 を削除(delete)するために、http://example.jp/resources/1/delete　
をGETしている。これはGETの目的である「リソースの取得」を完全に無視した使い方。

### ほかのメソッドでできることにPOSTを誤用した例
POSTの誤用とはほかに適切なメソッドが用意されているにもかかわらず、POSTでその機能を実現してしまうことです。
POSTの誤用の最たる例は XML-RPCとSOAP です。
~~~
POST /rpc HTTP/1.1 
Host:example.jp
Content-Type:application/xml
<methodCall>
<nethodName>getCount</methodName>
<params>
<param><value><string>http://gihyo.jp</string></value></param>
</params>
</methodCall>
~~~

### PUTがべき等でなくなる例
PUTでリソース内容の相対的な差分を送信すると、PUTはべき等でなくなります。PUTでは、そのリソースのなるベく完全な表現を送信するようにしましょう。この場合は、差分で表現するのではなく、変更後の値で表現するべきです。

### DELETEがべき等でなくなる例
http://example.jp/latest　<strong>というエイリアスリソース(ショートカット)を削除する</strong>ようにWeb サービスやWeb APIを実装した場合は、このリクエストはべき等です。DELETEを何度発行しても、/latest削除されているという結果は変わりません。
~~~
1回目のリクエスト
DELETE /Latest HTTP/1.1 
Host:example.jp

1回目のレスポンス 
HTTP/1.1 200 0K

2回目のリクエスト
DELETE /atest HTTP/1.1 
Host: example.jp

2回目のレスポンス 
HTTP/1.1 404 Not Found
Content-Type:text/plain;charset=utf-8
http://example.jp/latestは見つかりませんでした
~~~

/latest というエイリアスリソースではなく、<strong>/latestというURIが意味的に指し示す実際の最新バ-ジョンのリソ-ス(1.1など)を削除するうと,DELETE がべき等ではなくなってしまい、最初のDELETEでバ-ジョン1.2が削除され、次のDELETEで1.1か削除されてる。
~~~
1回目のリクエスト
DELETE /latest HTTP/1.1 
Host: example.jp

1回目のレスボンス 
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
http://example.jp/1.2を削除しました。

2回目のリクエスト
DELETE /latest HTTP/1.1 
Host:example.jp

2回目のレスポンス
HTTP/11 200 OK
Content-Type: text/plain; charset=utf-8
http://example.jp/1.1を削除しました。
~~~
#### 設計での解

* エイリアスリソースだけを削除できるように設計する
* 時間や状況で指し示すリソースが変化するリソース)は、特别な理由かない限り更新や削除などの操作ができないように設計する。