Clojure/Ring の middleware を使ってみる

最近は通勤電車で Clojure/Ring のコードを iPhone でだらだら読んでいます。

今回は ring/middleware を使ってみたいと思います。
使ってみるのはわかりやすいベーシック認証ミドルウェアです。

ベーシック認証ミドルウェア

Ring middleware for basic HTTP authentication.
https://github.com/adeel/ring-http-basic-auth/

導入方法

使い方は簡単です。
project.clj の dependencies に [ring-http-basic-auth "0.0.1"] を追加するだけ。このライブラリは clojure 1.3 だと動かないので、clojure 1.2.0 でお届けしています。

(defproject clj-snowflake "1.0.0-SNAPSHOT"
  :description "snowflake"
  :dependencies [[org.clojure/clojure "1.2.0"]
                 [ring "1.0.0-RC5"]
                 [ring-http-basic-auth "0.0.1"]
                 [compojure "1.0.0-SNAPSHOT"]
                 [clj-json "0.4.3"]
                 [clj-time "0.3.3"]]
  :main snowflake.core
  :dev-dependencies [[lein-ring "0.4.6"]]
  :ring {:handler snowflake.core/app})

次は middleware の設定です。まずは ring.middleware.http-basic-auth を読み込みます。
あとは認証を担当する関数を作ります、ここでは defn authenticate ですね。

めんどうなので demo/demodemo でログイン出来る様にハードコードしています。本来ならばここはデータベースなどに問い合わせるべきでしょう。

snowflake/core.clj

(ns snowflake.core
  (:gen-class)
  (:use compojure.core
        ring.adapter.jetty
        ring.middleware.http-basic-auth)
  (:require [clj-json.core :as json]
            [compojure.route :as route]
            [compojure.handler :as handler]))

(defn authenticate [username password]
  (if (and (= username "demo")
           (= password "demodemo"))
    {:username username}))

(defroutes public-routes
  (GET "/" [] (json/generate-string {"ログイン" "ページ"}))
  (route/resources "/"))

(defroutes protected-routes
  (GET "/admin" [] (json/generate-string {"管理" "ページ"}))
  (route/not-found "Page not found"))

(defroutes main-routes
  (wrap-with-auth public-routes authenticate)
  (wrap-require-auth protected-routes authenticate
    "The Secret Area" {:body "You're not allowed in The Secret Area!"}))

(def app (handler/site main-routes))

(defn -main []
  (let [port (Integer/parseInt (get (System/getenv) "PORT" "8080"))]
    (run-jetty main-routes {:port port})))

あとは middleware を差し込んでしまえば終わりです。

起動して http://127.0.0.1:3000/http://127.0.0.1:3000/admin にアクセスしてみましょう。

lein ring server

感想

コード自体はほとんどコピペです。

ring-http-basic-auth のコードをだらだら読んでいたのですが、結構しらない書き方とかが出てきて困ったり。Clojure 1.2 と 1.3 の違いとか調べておかないとダメですね。できる限り最新版を使っておきたい人なのですが、1.4 もどう変わるのかまとめておく必要ありそうですね。

あと lein 使っていて思ったのが、ローカルなリポジトリやライブラリを使い方を覚えておかないとなぁと思いました。Erlang のビルドツールである rebar は git や hg のリポジトリを直接参照できたりしたので楽だったのですが。

Clojure は結構色々解決する壁が多そうだなぁと言う印象です。環境構築系をしっかりまとめていく必要があると感じました。

また、1.4 がどう変わるのかとかもですね。

Ring/middleware ほとんど関係ない感想に ... 。

参考