【メモ】RESTでパラメータはどのように表現すべきか等

タイトルのようなことを悩み中。結論は出ない。本買ってちゃんと勉強しないと分からんかも。

とりあえず感覚をつかむために、ネットで検索したアンチパターンやベストプラクティス的なものを眺めてみる。

 

RESTfulなWebサイトと拡張子を含むURLについて より

例えば:

  • /blogs.jsp?id=hiyama&date=20100120

これはダメダメです。

拡張子.jspは、使用されているテクノロジを示すものです。リソースの本性には何の関係もなく、誰も知りたいとは思わない情報です。「URIは記述的であるべき」(『RESTful Webサービス』p.87)に反します。

クエリパラメータidとdateの値は、リソースを一意に識別する情報であり、計算処理への名前付き引数ではありません。これはクエリパラメータの誤用です。

とのこと。なんとなく分かる。「jspは要らない」、それは当然。分かる。「idとdateはリソースを一意に識別する情報であり名前付き引数でない」、これはちょっと良く感覚がつかめない。たとえば、

/blogs/hiyama/2010/01/20

だったら良いのかな?何故かと言われると…ちょっと説明できない。このコンテンツは静的な資源だからパラメータにしちゃいけない、みたいな感じかなあ。

例えば、次のクエリパラメータ付きURIを考えます。

/articles/search?words=Web+フレームワーク&lang=ja

これを次のように直したらクールだと本気で思っている人がいるようなのです。

/articles/search/words/Web%20フレームワーク/lang/ja

この例もなんとなく分かる。意味ない階層を無駄に作るべきじゃない。ただ、微妙なのが

/articles/search/page/2?words=Web+フレームワーク&lang=ja

だったら許されるような気がする。いくつかのページから成り立つという表現は自然であるというのが理由。これは良いの?ダメなの?

 

REST API Best practices: Where to put parameters? より

If you want to return a 404 error when the parameter value does not correspond to an existing resource then I would tend towards a path segment parameter. e.g. /customer/232 where 232 is not a valid customer id.

「404で資源がないことを表したい場合、パラメータではなくてパスセグメントで書くべき」、納得。

If however you want to return an empty list then when the parameter is not found then I suggest using query string parameters. e.g. /contacts?name=dave

「でもたとえばデータが無いときに空のリストとかを返したい場合はクエリ」なるほど。これが404返したらdaveのcontactsが無いのか、それともcontactsそのものが無いのか良くわからんからな。

If a parameter affects an entire subtree of your URI space then use a path segment. e.g. a language parameter /en/document/foo.txt versus /document/foo.txt?language=en

「パラメータがURIのサブツリー全体に影響するときはパスセグメント」、了解です。これはもう単に書くのが面倒ですな。

引用するには長すぎるので全文は引用しないけど、同じページに以下のような記述があった。

  1. Locators - E.g. resource identifiers such as IDs or action/view
  2. Filters - E.g. parameters that provide a search for, sorting or narrow down the set of results.
  3. State - E.g. session identification, api keys, whatevs.
  4. Content - E.g. data to be stored.

というような要素があり、それを

  1. Request headers & cookies
  2. URL query string ("GET" vars)
  3. URL paths
  4. Body query string/multipart ("POST" vars)

のいずれかで表現することになる。

Stateはリクエストヘッダ、Cookieでやるべしと書いている。異論の余地はないが、RESTでセッションをどう扱うべきかというのはもう少し掘り下げたい気はする。それは「状態」それ自体が文字通りステートフルなわけであって、Representationalには書けない気がするからだ。が、現状Cookieでやるしかない。セッションを表すキーをURLに入れ込むバカは居ないだろう。

Content(たとえばストアすべきデータ)はBodyになると書いている。それも異論の余地は無い。

LocatorはURLパスになるべきと書いている。LocatorとはたとえばID、アクション、ページ番号などだ。これに倣えば、私が先ほど書いたpage/2みたいなURIはRESTであると言えるのだろうか。

Filterは常にクエリ文字列だと言っている。

  • mysite.com/article/?query=Obama
  • /article/5?order=backwards

などがその例だ。ただし、

mysite.com/article/5?view=pdf

というViewの方法の仕方もfilterである(GETパラメータにすべき)という。これは見つかった資源を変化させて返すものであり、資源を追跡するようなものではないからだそうだ。これはちょっと同意できない。「見つかった資源を変化させて返すもの」というのはサーバ内部の処理であって要求するクライアントが関知すべき問題で無いとおもう。クライアント側から見たら「pdf」というサブツリーに同じようなデータがあるという記述方法の方がよりrepresentationalだと思うんですけど、どうですかね。

また、GETは長さに制限があるというのも気になる。基幹系システムとかを組んでいると、時々「絶対使わんだろ」と思うくらい多種多様な検索パラメータ(たとえば、JOB名称、JOB番号、JOB発効日、JOB担当部署、JOB種別、JOB完了日、JOB完了/未完了、JOB担当者、JOB客先名称、客先JOB番号…etc)を指定できるようにせよ、という仕様に頻繁に出くわすのだけど、そういうのはPOSTするしかない気がする。POSTは副作用が起こるものに使われるべきというのは分かるんだけどね。技術的な制限だよね。

まあ、こんなに多くのパラメータをGETで表現したところでRESTもクソも無いようjな気がしますが。日本人の(?)「とりあえず最大公約数や予期できる最大値を取っておけば安心」みたいな発想は何なんですかね。だからミニバンがバカ売れなんだよな。それは違うか?

結論

なんとなくわかったようなわかっていないような。

「RESTful Webサービス」というオライリー本があるのでこれを読めば一番いいのだけど、4000円とやっぱり高いのと、読んだ時間に見合うメリットがあるのかというと良くわからないのでいまいち買うのをためらう。だれか買った方が良いとか買わなくていいとか背中を押してください。