Ring周りについて頭を整理 その2〜Ringを生で使ってみる〜

Ring周りについて頭を整理 - oknknicの日記」に引き続き、Ring理解ネタ。
今回はRingを生で使ってみることで、理解を深める。

HelloWorld

  • プロジェクト(通常)の新規作成
lein new hello-ring
  • project.clj の編集
(defproject hello-ring "1.0.0-SNAPSHOT"
  :description "FIXME: write"
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [ring/ring-core "1.2.0"]
                 [ring/ring-jetty-adapter "1.2.0"]])
  • core.clj の編集
(ns hello-ring.core)

;ハンドラの定義
(defn handler [request]
  {:status 200                           ;レスポンスコード
   :headers {"Content-Type" "text/html"} ;レスポンスヘッダ
   :body "Hello World"})                 ;レスポンスボディ(String or ISeq or File or InputStream)
  • 起動(REPLから)
cd hello-ring
lein repl

(use 'ring.adapter.jetty) ;jettyアダプタの読み込み
(use 'hello-ring.core)
(run-jetty handler {:port 3000}) ;上記で定義したハンドラを指定して、jettyを起動
  • 接続確認

http://localhost:3000/

  :plugins [[lein-ring "0.8.5"]]
  :ring {:handler hello-ring.core/handler} ;ハンドラを指定
    • 起動
lein ring server

リクエストの中身を見てみる

  • core.clj
(ns hello-ring.core
    (use [clojure.string :only (join)]))

(defn handler [request]
  {:status 200
   :headers {"Content-Type" "text/html"}
   :body (join "<br/>"
            ["[server-port]"        (:server-port request)
             "[server-name]"        (:server-name request)
             "[remote-addr]"        (:remote-addr request)
             "[uri]"                (:uri request)
             "[query-string]"       (:query-string request)
             "[scheme]"             (:scheme request)
             "[request-method]"     (:request-method request)
             "[content-type]"       (:content-type request)
             "[content-length]"     (:content-length request)
             "[character-encoding]" (:character-encoding request)
             "[headers request]"    (:headers request)
             "[body]"               (:body request)])})

;もちろんこんな書き方もできる 
;(map
;  #(str "[" % "]" "<br/>" (% request) "<br/>")
;  (keys request))

レスポンス生成関数を使ってみる

  • response関数(基本的な200番のレスポンスを生成)
(ns hello-ring.core
    (:use ring.util.response))

(defn handler [request]
  (response "Hello ring"))

;以下のレスポンスが生成される
;{:status 200
; :headers {}
; :body "Hello ring"}
  • content-type関数(コンテンツタイプの設定)
(ns hello-ring.core
    (:use ring.util.response))

(defn handler [request]
  (-> (response "Hello World")
      (content-type "text/plain")))

;以下のレスポンスが生成される
;{:status 200
; :headers {"Content-Type" "text/plain"}
; :body "Hello ring"}
  • redirect関数
(ns hello-ring.core
    (:use ring.util.response))

(defn handler [request]
  (redirect "http://www.google.com"))

;以下のレスポンスが生成される(googleのホームページへリダイレクトされる)
;{:status 302
; :headers {"Location" "http://www.google.com"}
; :body ""}

その他関数(file-response等)や詳細情報は下記を参照のこと。

ミドルウェアかましてみる

  • wrap-params(パラメータマップを生成するミドルウェア。キーは「:params」)
(ns hello-ring.core
    (:use ring.util.response
          ring.middleware.params))

(defn handler [request]
  (response (str (:params request))))

(def middleware-applied-handler
  (wrap-params handler)) ;引数のハンドラにミドルウェア(ここではwrap-params)をかました新規ハンドラを生成
  • project.clj のハンドラ指定部分を以下のとおり変更
  :ring {:handler hello-ring.core/middleware-applied-handler}
  • 確認

http://localhost:3000/?param01=val01