[追記]「訂正補足:HTTPメソッド、URL、そして標準化された動詞」、「そろそろ決着、HTTPメソッド、URL、そして標準化された動詞」を書きましたので、あわせてお読みください。[/追記]
「HTTPメソッドの正統的使い方と現実的対処法」において、HTTPメソッドの本来の意味と、その本来の意味を損なわずにブラウザからリクエストする方法を述べました。最近また、Catyとの関係で、HTTPメソッドとURLをどう使うのが望ましいのか? という問題を考えました。
HTTPメソッドには、GET, PUT, DELETE, HEAD, POST がありますが、ブラウザから発行できるメソッドはGETとPOSTだけです。「HTTPメソッドの正統的使い方と現実的対処法」において、GET/POSTを使って他のメソッド(PUT, DELETE, HEAD)を表現するために、_methodというクエリパラメータを使用する方法(POSTのオーバーロード)を紹介しました。実際に使うメソッドと、_methodの値には、次の関係があります。
\ | get | put | delete | head | post |
---|---|---|---|---|---|
GETに乗せる | - | × | × | ○ | × |
POSTに乗せる | - | ○ | ○ | △ | - |
印の意味は次のとおりです; 「-」は無意味、「○」は有効、「×」はやってはいけない、「△」は無害だが必要性を見いだせない。
また、POSTの意味を細分するために、_submethodというクエリパラメータに、generate, append, process という値を指定して、結果的に7種の抽象的メソッドを列挙しました。
- get
- put
- delete
- head
- generate
- append
- process
上に要約した内容とほとんど同じなのですが、今回はCatyのメカニズムに即して動詞(verb)を考えました。動詞とは、上で「抽象的メソッド」と呼んだものと同じで、URLに対してリクエストするとき「そのURLをどうして欲しいのか」を指示する目印の記号です。ULRを目的語と考えて、動詞と呼ぶことにしました。(動詞という概念は、実はWindowsデスクトップで古くから使われていたものです。)
よく使いそうな動詞を列挙します。
- view :リソースを標準的な方法で表示する(上のget相当)。
- view-as-* :リソースを指定されたフォーマット/方法で表示する(view-as-html, view-as-textなど)。
- download :リソースをローカルコンピュータにダウンロードする。
- edit : 既存のリソースを編集する(編集用のUIを表示する)。
- process : 送られたデータを標準的な方法で処理する。
- create :新しいリソースをサーバー側に生成する(上のgenerate相当)。
- update :既存のリソースを上書きして変更する。
- append :既存のリソースに追加する。
- put : updateと同じだが、指定されたリソースがなければ新規に生成する。
- delete :指定されたリソースを削除する。
- exec :指定されたリソースは実行可能であり、それを実行する。
これらの動詞は、_verbというクエリパラメータで指定しますが、GET/POSTとの組み合わせは以下のようになります。([追記]この表には不適切な箇所があります。訂正はコチラ[/追記])
動詞 | GETメソッド | POSTメソッド | リソースは存在すべきか |
---|---|---|---|
デフォルト | view, exec | process, exec | - |
view | ○ | × | 存在 |
view-as-* | ○ | × | 存在 |
download | ○ | × | 存在 |
edit | ○ | × | 存在 |
process | × | ○ | 状況による |
create | × | ○ | 不在 |
update | × | ○ | 存在 |
append | × | ○ | 存在 |
put | × | ○ | どちらでもよい |
delete | × | ○ | 存在 |
exec | ○ | ○ | 存在 |
副作用がないリクエストはGETに乗せて、副作用を期待するリクエストはPOSTに乗せるのが原則です。これは,メイヤー先生(バートランド・メイヤー)の「クエリーとコマンド」という分類に対応します。
上の表の1行目の「デフォルト」とは、動詞が指定されなかったときの解釈です。GETならview、POSTならprocessがデフォルトであることは納得しやすいでしょう。ここで出てくるexecという動詞は、実行可能なURLを“実行する”ことを意味します。もし、指定されたURLが実行可能なら、デフォルト動詞はexecと解釈します。どんなURLが実行可能であるかは、Webアプリケーションごとに異なります。Catyのデフォルトでは、拡張子が「.cgi」であるURLは実行可能という単純なルールを採用しています。GETを通じて実行を指示することは許されますが、副作用を起こさないという原則を守りましょう。
URLに対応するリソースが存在するかしないかは事前にチェックされます。存在すべきリソースがないときは 404番や500番のエラーになります。processはデフォルト動詞であり、createの意味を含む可能性があるので「なければ生成する」(putと同じ)も(状況に依存して)認めました。editやappendも「なければ生成する」という選択肢もあるでしょうが、「ないものを(に) edit (append) できない」としました。実は、このあたりは絶対的な基準があるわけじゃないので、ルールが恣意的になってしまいますね。
編集操作は副作用を起こすのに、editという動詞をGETに乗せていることが変のように思えますが、動詞editは「編集を開始したい」という要求を伝えるだけです。例えば、http://example.jp/blog/2010-01-12.entry?_verb=edit は、リクエストの結果として http://example.jp/blog/2010-01-12.entry をすぐに変更してしまうわけではありません。編集UIを提供するページを送ってきます。その編集ページ内から、POST http://example.jp/blog/2010-01-12.entry?_verb=update として初めてリソースの変更がされます。
http://example.jp/blog/2010-01-12.entry?_verb=edit と同じ内容のリクエストは、http://example.jp/blog/editor.html?_verb=exec&entry=2010-01-12 とか、http://example.jp/blog/edit.cgi?entry=2010-01-12 のようにして発行してもいいでしょう。「動詞(verb)、目的語(URLのリソース)、入力データ(POSTデータ)、補助的な指定や情報(クエリーパラメータ)」を、HTTPリクエストのなかにできるだけ自然で分かりやすくエンコードしたいのですが、その方法が一意的に定まるわけではありません。それでも、人間にもソフトウェアにも扱いやすいルールはあるので、そのようなルールを策定して守るのがよろしかろうと思うのです。