前回、URI で特定できるリソースに HTTP の GET という動詞を適用して、 ある時点・条件での状態の表現を転送するのが REST だという説明をしました。 URI (名詞)に適用できる動詞は GET だけではありません。
今回は GET 以外の三つの動詞を紹介します。
前提知識
ここでは実際に稼動している REST 実装の例としてはてなブックマーク AtomAPI を使います。 はてなブックマークそのものの説明はしませんので、あらかじめご了承ください。
はてなブックマークに登録したひとつのブックマークを考えてみてください。 このひとつのブックマークエントリが、対象のリソースになります。 たとえば REST 入門の目次をブックマークしたとします。 このブックマークの URI は http://b.hatena.ne.jp/atom/edit/175062 です。 まずは GET してみましょう。
GET /atom/edit/175062 HTTP/1.1 Host: b.hatena.ne.jp X-WSSE: UsernameToken Username="yohei", ...
HTTP/1.1 200 OK Content-Type: application/x.atom+xml <entry xmlns="http://purl.org/atom/ns#"> <title>傭兵日記: REST 入門</title> <link rel="related" type="text/html" href="http://yohei-y.blogspot.com/2005/04/rest_23.html" /> <link rel="alternate" type="text/html" href="http://b.hatena.ne.jp/yohei/20050424#175062" /> <link rel="service.edit" type="application/x.atom+xml" href="http://b.hatena.ne.jp/atom/edit/175062" title="傭兵日記: REST 入門" /> <author> <name>yohei</name> </author> <generator url="http://b.hatena.ne.jp/" version="0.1" >Hatena::Bookmark</generator> <issued>2005-04-24T:14:46:00+9:00</issued> <id>tag:hatena.ne.jp,2005:bookmark-sample-175062</id> <summary type="text/plain">REST の入門</summary> </entry>
実際にはてなブックマークから GET するには認証用の X-WSSE ヘッダが必要なことに注意してください。 また、レスポンスに含まれるのは HTML ではなく XML 形式のブックマークとなります。 XML に含まれる情報で重要なのは title 要素と summary 要素になります。 summary 要素はいわゆる「コメント」です。
以下では、このブックマークエントリ(リソース)の URI に、 GET 以外の HTTP メソッドを適用してみます。
リソースを更新 -- PUT
一度は登録したけれど、つけたコメントが気に入らないので修正したいとします。 こんなときは HTTP の PUT メソッドを使います。PUT リクエストはこのようになります。
PUT /atom/edit/175062 HTTP/1.1 Host: b.hatena.ne.jp Content-Type: application/x.atom+xml X-WSSE: UsernameToken Username="yohei", ... <entry xmlns="http://purl.org/atom/ns#"> <summary type="text/plain" >REST(Representational State Transfer) の入門</summary> </entry>
PUT のレスポンスはこのようになります。
HTTP/1.1 200 OK
今、更新した URI を再度 GET することができます。
GET /atom/edit/175062 HTTP/1.1 Host: b.hatena.ne.jp X-WSSE: UsernameToken Username="yohei", ...
取得される XML は、コメントが修正されたものになっているはずです。
HTTP/1.1 200 OK Content-Type: application/x.atom+xml <entry xmlns="http://purl.org/atom/ns#"> <title>傭兵日記: REST 入門</title> <link rel="related" type="text/html" href="http://yohei-y.blogspot.com/2005/04/rest_23.html" /> <link rel="alternate" type="text/html" href="http://b.hatena.ne.jp/yohei/20050424#175062" /> <link rel="service.edit" type="application/x.atom+xml" href="http://b.hatena.ne.jp/atom/edit/175062" title="傭兵日記: REST 入門" /> <author> <name>yohei</name> </author> <generator url="http://b.hatena.ne.jp/" version="0.1" >Hatena::Bookmark</generator> <issued>2005-04-24T:14:46:00+9:00</issued> <id>tag:hatena.ne.jp,2005:bookmark-sample-175062</id> <summary type="text/plain" >REST(Representational State Transfer) の入門</summary> </entry>
リソースを削除 -- DELETE
ブックマークを削除したい場合は DELETE メソッドを使います。
DELETE /atom/edit/175062 HTTP/1.1 Host: b.hatena.ne.jp X-WSSE: UsernameToken Username="yohei", ...
HTTP/1.1 200 OK
DELETE が成功すると、同じ URI を再度 GET することはできません。
GET /atom/edit/175062 HTTP/1.1 Host: b.hatena.ne.jp X-WSSE: UsernameToken Username="yohei", ...
レスポンスは HTTP エラーになります。
HTTP/1.1 404 Not Found
リソースを新規作成 -- POST
先ほどのブックマーク、消してしまったけれどやっぱり元に戻したいとします。 そんなときは POST でブックマークリソースを新規に作成します。 でも、どの URI に POST したらよいのでしょうか。 リソースを新規に作成するわけですから、リソース自体がまだ存在せず、 したがって URI もありません。
こういう時はリソースを新規作成するためのリソースを用意します。 はてなブックマークではこのリソースの URI を PostURI と呼んでいます。 それでは POST してみましょう。
POST /atom/post HTTP/1.1 Host: b.hatena.ne.jp X-WSSE: UsernameToken Username="yohei", ... <entry xmlns="http://purl.org/atom/ns#"> <link rel="related" type="text/html" href="http://yohei-y.blogspot.com/2005/04/rest_23.html" /> <summary type="text/plain" >REST(Representational State Transfer) の入門</summary> </entry>
正常に受け付けられると以下のようなレスポンスが返ってきます。
HTTP/1.1 201 OK Content-Type: application/x.atom+xml Location: http://b.hatena.ne.jp/atom/edit/xxxx <entry xmlns="http://purl.org/atom/ns#"> <title>傭兵日記: REST 入門</title> <link rel="related" type="text/html" href="http://yohei-y.blogspot.com/2005/04/rest_23.html" /> <link rel="alternate" type="text/html" href="http://b.hatena.ne.jp/yohei/20050424#xxxx" /> <link rel="service.edit" type="application/x.atom+xml" href="http://b.hatena.ne.jp/atom/edit/xxxx" title="傭兵日記: REST 入門" /> <author> <name>yohei</name> </author> <generator url="http://b.hatena.ne.jp/" version="0.1" >Hatena::Bookmark</generator> <issued>2005-04-24T:17:46:00+9:00</issued> <id>tag:hatena.ne.jp,2005:bookmark-sample-xxxx</id> <summary type="text/plain" >REST(Representational State Transfer) の入門</summary> </entry>
レスポンスには Location ヘッダがあります。 これが新規作成されたリソースの URI になります。
POST メソッドは、その自由度の高さから、濫用される傾向にあります。 実際には GET, PUT, DELETE で行えることも、POST でできてしまうのです。 しかし、HTTP メソッド本来の意味を考えて POST メソッドを利用するのが正しいのは言うまでもありません。 POST を使うときの経験則として、POST をリソースの新規作成にだけ使う、 というものがあります。新しいリソースを POST する、と覚えましょう。 Paul Prescod の "Common REST Mistakes" の2番がこれに該当します。
まとめ
今回の POST, PUT, DELETE と、前回の GET はある点で大きく異なります。 それは GET がリソースの状態に影響を与えないのに対して、 それ以外の三つの動詞がリソースの状態に何らかの影響を与える可能性がある点です。 このような性質を副作用(side effect)といいます。 副作用のない GET はキャッシュという大きな可能性を持つことになります。 キャッシュについては機会があれば説明しようと思います。
これまでの内容をまとめると以下のようになります。
- GET はリソースを取得するメソッド
- PUT はリソースを更新するメソッド
- DELETE はリソースを削除するメソッド
- POST はリソースを新規作成するメソッド
- GET はリソースに副作用を与えない
REST では、リソースを操作するインターフェースにはこの四つのメソッドしかありません。 getXx() も setXx() も startXx() も createXx() もないのです。 これは REST アーキテクチャスタイルの持つ大きな制約のひとつ、 統一インターフェース(uniform interface)です。
次回は、Web の最大の特徴であるリンクと REST の関係について解説したいと思います。
[update 2005-05-22] POST と PUT についての記事を追加しました。
[update 2007-09-21] 2007年7月に Atom Publishing Protocol は標準化作業が終了しました。また、その技術解説を WEB+DB PRESS Vol.40 に書いています。
POSTのときPostURIは無くてはならないものなのでしょうか?
返信削除たとえば、
http://xxx.xxx/bookmark/
にPOSTすると、
http://xxx.xxx/bookmark/xxxxxx
と言うようなURIに新規作成されるのでは、駄目なんでしょうか?
PostURI は何でもいいんです。nagasawa さんの例の http://xxx.xxx/bookmark/ も PostURI と呼べると思います。
返信削除実は PostURI というのは古い Atom API 用語で、現時点での最新版では PostURI という用語は出てきません。そのかわりに、コレクションリソース(ブックマークでいえばブックマーク集のようなもの)の URI に POST することで新しいエントリが追加されるようになっています。
このページを読んで自分の手を動かして理解するためには"X-WSSE"のところが結構大きなネックになりそうです。関連ツールの紹介があるとよいのですが。
返信削除例えばeXeve(http://www.witha.jp/eXeries/ja/index.html)は便利です。
なんかPostURIというのがしっくり来ません。
返信削除PostURIにPostするのがOKなら、DeleteURIにPostすることでリソースを削除するのもOKな気がしますが。
Postする時点ではそのリソースのURIが無いから仕方なくPostURIというものを使うのでしょうか。
これが「仕方なく」か「そうでない」かの違いは小さくないのではないかと思います。
例えば、PostURIが一意に定まっておらず、存在しないURIに対してPostしたら新規作成、というような実装があってもかまわないのでしょうか?
連投すいません。
返信削除この4つ以外の動詞も使ってよいのでしょうか?
HEADとかOPTIONSとかWebDAVとか。