http://e-arrows.sakura.ne.jp/2011/05/what-ive-created-in-ariel.html
(eval-when (:compile-toplevel :load-toplevel :execute) (require :clack) (require :cl-markup) (require :drakma) ) (defpackage :sample-app (:use :cl :clack :clack.request :clack.app.route :cl-markup :drakma)) (in-package :sample-app) (defun sample-app-1 (env) " clackupから呼び出す関数。clackupより先に定義しておく必要がある これはリクエストヘッダを表示するだけのシンプルなもの clackupから呼び出された関数は最終的に (responst-code (head-list) (body-list)) という形式のリストを返す必要がある " (list 200 '(:content-type "text/plain") (list (format nil "~{~a: ~a~%~}~%" env)))) ;; clack の起動はシンプル。 ;; clackup の引数として関数を渡すことで、HTTPアクセス時にその関数が呼び出されるだけ。 ;; 呼び出された関数の引数はHTTPリクエストヘッダを格納したリストになる。 (clackup #'sample-app-1)
これを呼び出すと。
CL-USER> (drakma:http-request "http://localhost:5000/") "REQUEST-METHOD: GET SCRIPT-NAME: PATH-INFO: / SERVER-NAME: localhost SERVER-PORT: 5000 SERVER-PROTOCOL: HTTP/1.1 REQUEST-URI: / URL-SCHEME: HTTP REMOTE-ADDR: 127.0.0.1 REMOTE-PORT: 51862 QUERY-STRING: RAW-BODY: #<FLEXI-IO-STREAM #x2102A9B54D> CONTENT-LENGTH: NIL CONTENT-TYPE: NIL CLACK.UPLOADS: NIL CLACK-HANDLER: HUNCHENTOOT HTTP-HOST: localhost:5000 HTTP-USER-AGENT: Drakma/1.2.3 (Clozure Common Lisp Version 1.6-r14468M (WindowsX8664); Microsoft Windows; 6.1 Build 7601 (Workstation); http://weitz.de/drakma/) " 200 ((:CONTENT-LENGTH . "518") (:DATE . "Tue, 07 Jun 2011 13:36:39 GMT") (:SERVER . "Hunchentoot 1.1.1") (:CONNECTION . "Close") (:CONTENT-TYPE . "text/plain")) #<URI http://localhost:5000/> #<FLEXI-STREAMS:FLEXI-IO-STREAM #x2102A5FE6D> T "OK"
別のuriを呼び出すと。
CL-USER> (drakma:http-request "http://localhost:5000/index&get=data1") "REQUEST-METHOD: GET SCRIPT-NAME: PATH-INFO: /index&get=data1 SERVER-NAME: localhost SERVER-PORT: 5000 SERVER-PROTOCOL: HTTP/1.1 REQUEST-URI: /index&get=data1 URL-SCHEME: HTTP REMOTE-ADDR: 127.0.0.1 REMOTE-PORT: 52059 QUERY-STRING: RAW-BODY: #<FLEXI-IO-STREAM #x2102BDD29D> CONTENT-LENGTH: NIL CONTENT-TYPE: NIL CLACK.UPLOADS: NIL CLACK-HANDLER: HUNCHENTOOT HTTP-HOST: localhost:5000 HTTP-USER-AGENT: Drakma/1.2.3 (Clozure Common Lisp Version 1.6-r14468M (WindowsX8664); Microsoft Windows; 6.1 Build 7601 (Workstation); http://weitz.de/drakma/) " 200 ((:CONTENT-LENGTH . "548") (:DATE . "Tue, 07 Jun 2011 13:43:34 GMT") (:SERVER . "Hunchentoot 1.1.1") (:CONNECTION . "Close") (:CONTENT-TYPE . "text/plain")) #<URI http://localhost:5000/index&get=data1> #<FLEXI-STREAMS:FLEXI-IO-STREAM #x2102A5428D> T "OK"
ClackではどんなURIを指定しても、たとえば / でも /index でも /post?xxx=yyy でも全て最初に指定した関数が呼び出される。
ページ単位の処理の記述する場合は、:request-uriを見てアクセスページごとに処理を振り分ける必要がある。手で書くこともできるが、単純な振り分けはclack.app.routeに含まれるdefroutesでシンプルに指定できる。
(defroutes sample-app-2 (env) (GET "/" #'index) ;; GET で / が呼ばれたら関数 index を呼び出す (GET "/index" #'index) ;; GET で /index でも 関数 index を呼び出す (POST "/post" #'post)) ;; POST で /post が呼び出されたら関数 post を呼び出す ;; このマクロは以下のように展開され、 ;; 存在しないページはちゃんと404を返してくれる ;; ;; (DEFUN SAMPALE-APP-2 (#:REQ0) ;; (LET ((#:REQUEST-METHOD1 (GETF #:REQ0 :REQUEST-METHOD)) ;; (#:REQUEST-PATH2 (GETF #:REQ0 :PATH-INFO))) ;; (DECLARE (IGNORABLE #:REQUEST-METHOD1 #:REQUEST-PATH2)) ;; (OR (WHEN (STRING= #:REQUEST-METHOD1 'ENV) ;; (MULTIPLE-VALUE-BIND (#:MATCHED3 #:REGS4) ;; (CL-PPCRE:SCAN-TO-STRINGS "^$" #:REQUEST-PATH2) ;; (DECLARE (IGNORABLE #:REGS4)) ;; (IF #:MATCHED3 (CALL NIL #:REQ0)))) ;; (WHEN (STRING= #:REQUEST-METHOD1 'GET) ;; (MULTIPLE-VALUE-BIND (#:MATCHED3 #:REGS4) ;; (CL-PPCRE:SCAN-TO-STRINGS "^/$" #:REQUEST-PATH2) ;; (DECLARE (IGNORABLE #:REGS4)) ;; (IF #:MATCHED3 (CALL #'INDEX #:REQ0)))) ;; (WHEN (STRING= #:REQUEST-METHOD1 'GET) ;; (MULTIPLE-VALUE-BIND (#:MATCHED3 #:REGS4) ;; (CL-PPCRE:SCAN-TO-STRINGS "^/index$" #:REQUEST-PATH2) ;; (DECLARE (IGNORABLE #:REGS4)) ;; (IF #:MATCHED3 (CALL #'INDEX #:REQ0)))) ;; (WHEN (STRING= #:REQUEST-METHOD1 'POST) ;; (MULTIPLE-VALUE-BIND (#:MATCHED3 #:REGS4) ;; (CL-PPCRE:SCAN-TO-STRINGS "^/post$" #:REQUEST-PATH2) ;; (DECLARE (IGNORABLE #:REGS4)) ;; (IF #:MATCHED3 (CALL #'POST #:REQ0)))) ;; (LIST 404 NIL NIL)))) (defun index (env) "#\Linefeedは出力をわかりやすくするためにつけているだけなので実際は不要" `(200 (:content-type "text/html") ,(list (markup (html (:head (:meta :content "text/html" :charset "UTF-8") #\Linefeed (:title "Clackへようこそ!") #\Linefeed) (:body :bgcolor "efefef" (:p "Clackへようこそ!") (:br) #\Linefeed "cl-markup では &<>\"が自動エスケープされます")))))) (defun post (env) " postデータを受け取る いったんmake-requestでリクエストヘッダをクラスインスタンスへ格納し、 そこからbody-parameterで取り出す事ができる。 " (let ((req (make-request env))) `(200 (:content-type "text/plain") ("post data: " ,(body-parameter req "name"))))) (clackup #'sample-app-2)
まずは普通に呼び出してみる
CL-USER> (drakma:http-request "http://localhost:5000") "<html><head><meta content=\"text/html\" charset=\"UTF-8\" /> <title>Clackへようこそ!</title> </head><body bgcolor=\"efefef\"><p>Clackへようこそ!</p><br /> cl-markup では &<>"が自動エスケープされます</body></html>" 200 ((:CONTENT-LENGTH . "249") (:DATE . "Tue, 07 Jun 2011 14:19:59 GMT") (:SERVER . "Hunchentoot 1.1.1") (:CONNECTION . "Close") (:CONTENT-TYPE . "text/html")) #<URI http://localhost:5000/> #<FLEXI-STREAMS:FLEXI-IO-STREAM #x2104109E0D> T "OK"
別の呼び出し方
CL-USER> (drakma:http-request "http://localhost:5000/index") "<html><head><meta content=\"text/html\" charset=\"UTF-8\" /> <title>Clackへようこそ!</title> </head><body bgcolor=\"efefef\"><p>Clackへようこそ!</p><br /> cl-markup では &<>"が自動エスケープされます</body></html>" 200 ((:CONTENT-LENGTH . "249") (:DATE . "Tue, 07 Jun 2011 14:20:06 GMT") (:SERVER . "Hunchentoot 1.1.1") (:CONNECTION . "Close") (:CONTENT-TYPE . "text/html")) #<URI http://localhost:5000/index> #<FLEXI-STREAMS:FLEXI-IO-STREAM #x21041BDF4D> T "OK"
存在しないページを呼び出す
CL-USER> (drakma:http-request "http://localhost:5000/404") NIL 404 ((:CONTENT-LENGTH . "0") (:DATE . "Tue, 07 Jun 2011 14:20:10 GMT") (:SERVER . "Hunchentoot 1.1.1") (:CONNECTION . "Close") (:CONTENT-TYPE . "text/html; charset=utf-8")) #<URI http://localhost:5000/404> #<FLEXI-STREAMS:FLEXI-IO-STREAM #x2104002DDD> T "Not Found"
POSTデータを送信する。
CL-USER> (let ((temp "name=data1")) (drakma:http-request "http://localhost:5000/post" :method :post :content temp :content-length (length temp))) "post data: data1" 200 ((:CONTENT-LENGTH . "17") (:DATE . "Tue, 07 Jun 2011 14:20:19 GMT") (:SERVER . "Hunchentoot 1.1.1") (:CONNECTION . "Close") (:CONTENT-TYPE . "text/plain")) #<URI http://localhost:5000/post> #<FLEXI-STREAMS:FLEXI-IO-STREAM #x2104055CED> T "OK"
0 件のコメント:
コメントを投稿