http-method

Webの成功理由は制約 8つしかないHTTPメソッド

前回は、TCP/IPをベースとしたプロトコルであるHTTPの基本についてまとめた。ここでは、Webの成功理由とも言われる8つのHTTPメソッド、特にGET、POST、PUT、DELETE、HEAD、OPTIONSについて説明する。

1 8つしかないメソッド

HTTPには、クライアントが行いたい処理をサーバに伝えるという重要な役割がある。HTTP 1.1においてその役割を果たすのが、以下の8つのメソッドである。ここでは、ほとんど使われていないTRACEとCONNECTを除いた6つのメソッドについて解説する。

  1. GET   :リソースの取得
  2. POST   :子リソースの作成、リソースへのデータの追加、その他の処理
  3. PUT   :リソースの更新、リソースの作成
  4. DELETE  :リソースの削除
  5. HEAD   :リソースのヘッダ(メタデータ)の取得
  6. OPTIONS   :リソースがサポートしているメソッドの取得
  7. TRACE    :自分宛にリクエストメッセージを返す(ループバック)試験
  8. CONNECT:プロキシ動作のトンネル接続への変更

 

2 HTTPメソッドとCRUD

CRUDとは、Create(作成—POST/PUT)、Read(読み込み—GET)、Update(更新—PUT)、Delete(削除—DELETE)というデータ操作の基本となる4つの処理のことである。HTTPメソッドにおいてはGET、POST、PUT、DELETEが満たす性質である。

 

3 GET—リソースの取得

GETは指定したURIの情報を取得する。最も利用頻度の高いメソッドで、Webページの取得、画像の取得、映像の取得、フィードの取得などにおいて発行される。

 

4 POST—リソースの作成

POSTには以下の3つの役割がある。

 

子リソースの作成

POSTの代表的な機能は、あるリソースに対する子リソースの作成である。ブログ記事の投稿などの操作で使われる。

 

リソースへのデータの追加

POSTの2つ目の機能は、既存リソースへのデータの追加である。

 

他のメソッドでは対応できない処理

POSTの3つ目の機能は、他のメソッドでは対応できない処理の実行である。例えば、GETではURIに含めていたキーワードを、POSTではリクエストボディに入れられる。

 

5 PUT—リソースの更新、作成

PUTは以下の2つの機能を持っている。

 

リソースの更新

PUTの1つ目の機能は、リソースの更新である。PUTへのレスポンスはボディに結果を入れてもいいし、ボディには何も入れずに204 No Contentを返しても構わない。

 

リソースの作成

PUTの2つ目の機能は、リソースの作成である。

 

POSTとPUTの使い分け

POSTとPUTの使い分けは、URIの決定権がクライアントとサーバのどちらにあるかがポイントである。つまり、URIの決定権がクライアントにあるものがPUT(Wikipediaなど)、サーバにあるものがPOST(Twitterなど)である。特別な理由がない限りは、リソースの作成はPOSTで行いURIもサーバ側で決定する、という設計が望ましい。

 

6 DELETE—リソースの削除

DELETEとは、リソースを削除するメソッドである。一般的にDELETEのレスポンスはボディを持たない。

 

7 HEAD—リソースのヘッダの取得

GETがリソースを取得するメソッドなのに対し、HEADはリソースのヘッダ(メタデータ)だけを取得するメソッドである。HEADへのレスポンスにはボディが含まれない。この性質を利用すると、ネットワークの帯域を節約しながらリソースの大きさを調べたり、リソースの更新日時を取得したりできる。

 

8 OPTIONS—リソースがサポートしているメソッドの取得

OPTIONはそのリソースがサポートしているメソッドの一覧を返す。レスポンスに含まれるAllowヘッダは、そのリソースが許可するメソッドの一覧である。OPTIONを実装する場合、多くのWebアプリケーションフレームワークでは、リソースごとに対応しているメソッドを返すように自前で実装しなければならない。

 

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

これまで説明してきた6つが主なHTTPメソッドである。しかし、携帯電話向けブラウザやセキュリティ上の理由から、GETとPOST以外のアクセスを制限している場合もある。このような状況でサーバにPUTやDELETEを伝える方法には、以下の2つがある。

 

_methodパラメータ

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

 

X-HTTP-Method-Override

X-HTTP-Method-Overrideヘッダを用いる方法とは、POSTの内容がXMLなど、application/x-www-form-urlencoded以外の場合に利用できるものである。GoogleのGData(Google Data Protocol)が採用している。

 

10 条件付きリクエスト

条件付きリクエスト(Conditional Request)とは、HTTPメソッドと更新日時などのヘッダを組み合わせることで、メソッドを実行するかどうかをリソースの更新日時を条件にサーバが選択できるようになるものである。例えば、GETにリソースの更新日時を条件として入れるには、If-Modified-Sinceヘッダを使う。

 

11 べき等性と安全性

HTTPメソッドはその性質によって以下の3つに分類できる。べき等(Idempotence)とは、ある操作を何回行っても結果が同じことを意味する数学用語である。安全(Safe)とは、操作対象のリソースの状態を変化させない(副作用がない)ことを意味する。

  • GET、HEAD :べき等かつ安全
  • PUT、DELETE:べき等だが安全でない
  • POST    :べき等でも安全でもない

 

PUTはべき等

PUTはべき等なため、同じPUTを2回送信したとしても、結果は1回送信したときと同じになる。

 

DELETEもべき等

DELETEもべき等なため、2回送信したとしても結果は同じである(返ってくるステータスコードは異なる)。

 

GETとHEADもべき等、そのうえ安全

GETとHEADもべき等であり、そのうえ安全なため、結果もリソースの状態も変化させない。

 

安全でもべき等でもないPOST

POSTは安全でもべき等でもないため、複数回送ることに慎重でなければならない。例えば、ショッピングサイトなどで二重注文をしてしまうことがある。

 

12 メソッドの誤用

GETが安全でなくなる例

GETでリソースを更新したり、リソースを削除したりするのは誤った利用方法である。

 

他のメソッドでできることにPOSTを誤用した例

POSTの誤用とは、他に適切なメソッドが用意されているにもかかわらず、POSTでその機能を実現してしまうことである。例えば、GET、PUT、DELETEで実現できる機能をPOSTで実現してしまうと、この3つのメソッドが持つ性質が利用できなくなる。また、XML-RPCとSOAPも誤用の例である。どちらもRPCを実現するためのプロトコルであるが、すべての関数呼び出しをPOSTで実現するように設計されているのである。

 

PUTがべき等でなくなる例

PUTがべき等でなくなる例は、リソース内容の相対的な差分を送信するときである。例えば、価格を(+50)で表現するのではなく、変更後の値(150)で表現すべきである。

 

DELETEがべき等でなくなる例

DELETEがべき等でなくなる例は、エイリアスリソース(ショートカット)のような特殊なリソースを削除する際に起こる。そのため、そういったリソースは特別な理由がない限り更新や削除などの操作ができないように設計する必要がある。

 

13 Webの成功理由はHTTPメソッドにあり

Webの成功理由は、8つしかないHTTPメソッドにある。すなわち、これこそがRESTの統一インタフェースである(Webのアーキテクチャスタイル(設計思想) REST参照)。メソッドを限定して固定したからこそプロトコルがシンプルに保たれ、Webは成功したのである。

 

最後に

GETに隠された安全性、PUTとDELETEのべき等性、そしていざとなったらなんでもできるPOST。HTTPはそれぞれのメソッドにあった性質と拡張性を備えた、優れたプロトコルと言える。

次回は、レスポンスメッセージの意味を伝える数字であるステータスコードについてまとめる。

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB DB PRESS plus)


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>