Clojure Web Development勉強 - Ring (その5) ルーティング
というわけでついにルーティング。
そもそもルーティングとは?
今まではどのリンクを踏んでも同じコンテンツしか見えないという「お前htmlメモ帳に直打ちしてftpでアップロードしてた頃のサイトの方がよっぽど動的なんだけどどうなの?」と煽られてしまうような有様だったのだが、ようやく「uriやparamsによってどのようなページを表示するかをプログラム上で決定する」という機能を実装する。この機能がルーティング。
前回のプログラムにルーティングを実装したコードがこちら:
変更したのはhandler.cljとcore.cljの2ファイル。
handler.cljでの変更: - get/postからのクエリパラメータを使って非常に簡単な動的HTML作成を実施するdisplay-result関数 - リクエストマップの中のuriやparamsフィールドなどを調べ、正しいhandlerへのルーティングを担当するhandler-with-routing関数 - コードの整理(使わないplain-textやredirect関数を削ったり、微妙に表示されるhtmlを変更したり)
core.cljでは単にhandler-with-routing関数を大本のhandlerとして使うように変更したのみ。
display-result関数の中身:
(defn display-result [req] (let [{:keys [params uri]} req param-name (get params "name") req-type (if (= uri "/get-submit") "GET" "POST")] (-> (res/response (str "<div> <h1>Hello " param-name "!</h1> <p>Submitted via a " req-type " request.</p> <p><a href='..'>Return to main page</p> </div>")) (res/content-type "text/html"))))
destructuringでリクエストマップからparamsとuriをとり、さらにparamsから"name"フィールド、uriがpost-submitかget-submitかによってreq-typeを"GET"か"POST"に束縛して、名前とリクエストタイプを表示する。言ってしまえばそれだけだが、最低限の動的な機能は備えている。
そしてルーター部分:
(defn handler-with-routing [req] (println "In Routing Handler!") (let [{:keys [uri params request-method]} req] (cond (= uri "/") (main req) (= uri "/get-form.html") (get-form req) (= uri "/post-form.html") (post-form req) (= uri "/get-submit") (display-result req) (= uri "/post-submit") (display-result req) :else (not-found req))))
ちなみに私はどーしてもラウター、ラウティングと読んでしまう・・・
まあボイラープレートっぽい(= uri ...) (... req)
が並んでいる時点でLisperなら誰でも「おっ、マクロの時間だ」と思うわけで、近いうちに使ってみることになるCompojureというライブラリも基本的にこの部分を簡略化した上で強力なパターンマッチング機能を提供するマクロ群だ。
しかし、見栄えは別にして、これでこのサーバ上で何かのページにアクセスしようとした場合はこの関数を通してuriマッチングが行われて正しいページに送られるようになったわけだ。この関数に載っていないuriの場合は:elseのところにかかって(not-found req)から404メッセージが表示される。
ここからはring以外のライブラリ、特にcompojureとhiccupを見ていきたい。compojureでルーティング周りを、そしてhiccupでhtmlページの記述をより洗練させていきたい。