cl-markupはcl-whoと挙動が違うので使うときは注意が必要。
(eval-when (:compile-toplevel :load-toplevel :execute)
(require :clack)
(require :cl-markup)
(require :cl-ppcre)
(require :drakma)
)
(defpackage :sample-app
(:use :cl
:clack
:clack.request
:clack.app.route
:clack.builder
:clack.session.state.cookie
:clack.middleware.session
:cl-markup
:cl-ppcre
:drakma
))
(in-package :sample-app)
(defroutes sample-session-app (env)
(GET "/" #'index) ; トップページ。
(GET "/getdata" #'getdata) ; GETによるデータ受け渡し
(POST "/postdata" #'postdata) ; POSTによるデータ受け渡し
(GET "/session" #'session)) ; sessionによるデータの受け渡し
(defun index (env)
"トップページを生成
最初にセッションに変数を代入している。"
(setf (gethash :data1 (getf env :clack.session)) "データ1")
(setf (gethash :data2 (getf env :clack.session)) "データ2")
(setf (gethash :data3 (getf env :clack.session)) '("データ3-1" "データ3-2" "データ3-3"))
`(200
(:content-type "text/html")
(,(markup
(html
(:head
(:meta :content "text/html" :charset "UTF-8")
(:title "index"))
(:body
;; GETデータを送信するフォーム
(:form :method "get" :action "/getdata"
"GET"
(:input :type "text" :name "getname")
(:input :type "submit"))
;; POSTデータを送信するフォーム
(:form :method "post" :action "/postdata"
"POST"
(:input :type "text" :name "postname")
(:input :type "submit"))
(:br)
;; セッションデータを確認する画面へのリンク
(:a :href "/session" "セッションテスト")
))))))
(defun get-parameter (uri)
"URIからGETデータを分離する適当な関数"
(when (cl-ppcre:scan "\\?" uri)
(let ((get-data (second (cl-ppcre:split "\\?" uri))))
(when get-data
(mapcar #'(lambda (x) (cl-ppcre:split "\\=" x))
(cl-ppcre:split "\\&" get-data))))))
(defun getdata (env)
"GETされたデータを表示する"
`(200
(:content-type "text/html")
(,(markup
(html
(:head
(:meta :content "text/html" :charset "UTF-8")
(:title "get"))
(:body
(loop for i in (get-parameter (getf env :request-uri))
collect (format nil "~a" (hunchentoot:url-decode (second i))))
))))))
(defun postdata (env)
"POSTされたデータを表示する"
(let ((req (make-request env)))
`(200
(:content-type "text/html")
(,(markup
(html
(:head
(:meta :content "text/html" :charset "UTF-8")
(:title "post"))
(:body
"post data: " (body-parameter req "postname"))))))))
(defun session (env)
"セッションデータを表示する"
`(200
(:content-type "text/html")
(,(markup
(html
(:head
(:meta :content "text/html" :charset "UTF-8")
(:title "session"))
(:body
(gethash :data1 (getf env :clack.session)) (:br)
(gethash :data2 (getf env :clack.session)) (:br)
(loop for i in (gethash :data3 (getf env :clack.session))
collect (markup (:span i (:br))))
))))))
;; セッションを有効にしてClackを起動
(clackup
(builder (<clack-middleware-session> :state (make-instance '<clack-session-state-cookie>))
#'sample-session-app))
SESSIONを有効にしてトップページにアクセスするとCookieが挿入されるようになる。
CL-USER> (drakma:http-request "http://localhost:5000") "<html><head><meta content=\"text/html\" charset=\"UTF-8\" /><title>test</title></head><body><form method=\"get\" action=\"/getdata\">GET<input type=\"text\" name=\"getname\" /><input type=\"submit\" /></form><form method=\"post\" action=\"/postdata\">POST<input type=\"text\" name=\"postname\" /><input type=\"submit\" /></form><br /><a href=\"/session\">セッションテスト</a></body></html>" 200 ((:CONTENT-LENGTH . "371") (:DATE . "Wed, 08 Jun 2011 22:08:11 GMT") (:SERVER . "Hunchentoot 1.1.1") (:CONNECTION . "Close") (:SET-COOKIE . "CLACK.SESSION=dd878a54b3570f7bb06236358ebe56194ff6b848; path=/; expires=Sat, 14 Nov 2122 18:59:08 GMT") (:CONTENT-TYPE . "text/html")) #<URI http://localhost:5000/> #<FLEXI-STREAMS:FLEXI-IO-STREAM #x2103B8F79D> T "OK"この状態でブラウザからlocalhost:5000へアクセスし、フォームに入力してSUBMITボタンを押せばデータの受け渡しが確認できる。
cl-markupはcl-whoとは使い勝手が違うのでちょっと注意が必要。loopで回して直接文字列を出力(タグを使わない)場合は以下みたいにする(のが正しいのかな?)
CL-USER> (markup
(html
(:body
(loop for i in '(1 2 3 4 5)
collect (format nil "~a<br />~%" i)))))
"<html><body>1<br />
2<br />
3<br />
4<br />
5<br />
</body></html>"
1 件のコメント:
get-parameterは、Clack.Requestのquery-parameterで取れます
http://clacklisp.org/doc/clack.request.html
> cl-markupはcl-whoとは使い勝手が違うのでちょっと注意が必要。loopで回して直接文字列を出力(タグを使わない)場合は以下みたいにする(のが正しいのかな?)
正しいです。もし<br />をmarkupで書きたければ、
(loop for i in '(1 2 3 4 5)
collect (princ-to-string i)
collect (markup (:br)))
コメントを投稿