2008-10-27

hunchentootでREST

hunchentootでログイン処理 というエントリでセッションを使ったログインのコードを作って得意げになっていたわけだが、さらに勉強を進めてみると時代は今 RESTful であるらしい。
そして RESTful な設計ではセッションプげらであるらしい。
この REST なるものがこれからの(もうすでに?)トレンドのようなのだ。

RESTアーキテクチャはHTTPの原点に戻りステートレスな構造なのでキャッシュや分散処理など昨今の多数のユーザを抱えるWebアプリのスケーラビリティとの相性の良さから俄然注目されているんだそうな。それにステートレスだとブラウザでブックマークが楽だ。これって結構重要なのではないか?
ステートレスでどうやってセッション持つんだよう、って思うかもしれないけど、目から鱗の発想の転換がそこにはあった。URLの遷移がすなわちステート遷移なんである。まそれは置いといて。

RESTではリソースとURLを直接に対応させる。そしてHTTPのプロトコルそのものが既に持っているコマンドでリソースの取得、更新、削除などを指示する。
そのURLはこんな感じになる。
http://example.com/item/10

普通にブラウザのアドレスバーに入れればid:10のitemを取得できる。idのところが可変なんですな。

これをhunchentootで実装してみよう。まさにこのための関数が用意されていた。

(create-regex-dispatcher "/item/(\\d+)?" 'item)


ところがこの関数せっかく正規表現でマッチしてるのにマッチしたグループの情報(括弧でくくった\d+のマッチ)をあとから取れないのである。なぜならitem関数のところにわたせるのは無引数関数だけだから。

こんなんじゃないといけない。
(defun item ()
...)

こういうふうにしたい。
(defun item (idstr)
...)


いや、引数で渡されなくても関数内でリクエスト文字列ともう一度マッチとれば必要な情報は得られるけど無駄だし使い勝手も悪い。
というわけで、create-regex-dispatcherのマッチグループを引数で受けられるバージョンを作ってみた。

(defun create-regex-dispatcher/var (regex page-function)
(let ((scanner (cl-ppcre:create-scanner regex)))
(lambda (request)
(multiple-value-bind (match regs)
(cl-ppcre:scan-to-strings scanner (script-name request))
(when match
(lambda ()
(apply page-function (coerce regs 'list))))))))

あとは、
(create-regex-dispatcher/var "/item/(\\d+)?" 'item)


hunchentootのデフォルトのディスパッチャが無引数関数を要求してるので、それにあわせるために無引数クロージャを作って返してるだけである。

hunchentootでRESTっていうかその準備みたいになったけど、まあ簡単に拡張できるよって事で。

0 件のコメント: