Lisp 网络故事:如何修复 blogdemo 示例(第 4 章)?

Mar*_*ann 5 common-lisp

我看到 Pavel 的关于使用 CL 和RESTAS作为框架编写 Web 应用程序的教程。虽然简单的例子有效。我无法运行第 4 章中的博客示例。Hello, World!

使用(restas:debug-mode-on)我最终得到以下回溯:

invalid number of arguments: 0
  [Condition of type SB-INT:SIMPLE-PROGRAM-ERROR]

Restarts:
 0: [ABORT] abort thread (#<THREAD "hunchentoot-worker-127.0.0.1:59876" RUNNING {1009975FD3}>)

Backtrace:
  0: (BLOGDEMO::HTML-FRAME) [tl,external]
  1: (RESTAS::ROUTE-RENDER-METHOD #<RESTAS:ROUTE {100A16FE53}>)
  2: ((:METHOD RESTAS:PROCESS-ROUTE (RESTAS:ROUTE T)) #<RESTAS:ROUTE {100A16FE53}> NIL) [fast-method]
  3: ((FLET CALL-NEXT-METHOD :IN "C:/Users/martin_b/portacle/quicklisp/dists/quicklisp/software/restas-20170124-git/src/route.lisp"))
  4: ((:METHOD RESTAS:PROCESS-ROUTE :AROUND (ROUTES:BASE-ROUTE T)) #<RESTAS:ROUTE {100A16FE53}> NIL) [fast-method]
  5: (RESTAS::RESTAS-DISPATCH-REQUEST #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<RESTAS::RESTAS-REQUEST {1003E5B383}>)
  6: ((:METHOD HUNCHENTOOT:ACCEPTOR-DISPATCH-REQUEST (RESTAS:RESTAS-ACCEPTOR T)) #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<RESTAS::RESTAS-REQUEST {1003E5B383}>) [fast-method]
  7: ((:METHOD HUNCHENTOOT:HANDLE-REQUEST (HUNCHENTOOT:ACCEPTOR HUNCHENTOOT:REQUEST)) #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<RESTAS::RESTAS-REQUEST {1003E5B383}>) [fast-method]
  8: ((:METHOD HUNCHENTOOT:PROCESS-REQUEST (T)) #<RESTAS::RESTAS-REQUEST {1003E5B383}>) [fast-method]
  9: ((FLET CALL-NEXT-METHOD :IN "C:/Users/martin_b/portacle/quicklisp/dists/quicklisp/software/restas-20170124-git/src/hunchentoot.lisp"))
 10: ((:METHOD HUNCHENTOOT:PROCESS-REQUEST :AROUND (RESTAS::RESTAS-REQUEST)) #<RESTAS::RESTAS-REQUEST {1003E5B383}>) [fast-method]
 11: ((LAMBDA NIL :IN HUNCHENTOOT:PROCESS-CONNECTION))
 12: (HUNCHENTOOT::DO-WITH-ACCEPTOR-REQUEST-COUNT-INCREMENTED #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<CLOSURE (LAMBDA NIL :IN HUNCHENTOOT:PROCESS-CONNECTION) {1003C3439B}>)
 13: ((:METHOD HUNCHENTOOT:PROCESS-CONNECTION (HUNCHENTOOT:ACCEPTOR T)) #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<USOCKET:STREAM-USOCKET {1009971333}>) [fast-method]
 14: ((FLET CALL-NEXT-METHOD :IN "C:/Users/martin_b/portacle/quicklisp/dists/quicklisp/software/hunchentoot-1.2.35/acceptor.lisp"))
 15: ((:METHOD HUNCHENTOOT:PROCESS-CONNECTION :AROUND (HUNCHENTOOT:ACCEPTOR T)) #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<USOCKET:STREAM-USOCKET {1009971333}>) [fast-method]
 16: ((FLET HUNCHENTOOT::PROCESS-CONNECTION% :IN HUNCHENTOOT::HANDLE-INCOMING-CONNECTION%) #<RESTAS:RESTAS-ACCEPTOR (host *, port 8080)> #<USOCKET:STREAM-USOCKET {1009971333}>)
 17: ((:METHOD HUNCHENTOOT::HANDLE-INCOMING-CONNECTION% (HUNCHENTOOT:ONE-THREAD-PER-CONNECTION-TASKMASTER T)) #<HUNCHENTOOT:ONE-THREAD-PER-CONNECTION-TASKMASTER {10081F24C3}> #<USOCKET:STREAM-USOCKET {1009..
 18: ((LAMBDA NIL :IN HUNCHENTOOT:CREATE-REQUEST-HANDLER-THREAD))
 19: ((LAMBDA NIL :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS))
 20: ((FLET #:WITHOUT-INTERRUPTS-BODY-1169 :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE))
 21: ((FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE))
 22: ((FLET #:WITHOUT-INTERRUPTS-BODY-359 :IN SB-THREAD::CALL-WITH-MUTEX))
 23: (SB-THREAD::CALL-WITH-MUTEX #<CLOSURE (FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE) {6DAFB4B}> #<SB-THREAD:MUTEX "thread result lock" owner: #<SB-THREAD:THREAD "..
 24: (SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE #<SB-THREAD:THREAD "hunchentoot-worker-127.0.0.1:59876" RUNNING {1009975FD3}> NIL #<CLOSURE (LAMBDA NIL :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS) {..
 25: ("foreign function: #x42BEFC")
 26: ("foreign function: #x4038C1")
 27: ("foreign function: #x447080")
Run Code Online (Sandbox Code Playgroud)

显然,函数期望的参数数量html-frame和调用它的参数数量之间存在问题render-method之间存在问题。我检查了源代码和 RESTAS 文档(似乎有点过时),但不明白要更改什么。

有人用RESTAS吗?还有其他最新的现实生活例子可以学习吗?我对 Cliki 的印象是,周围有几个网络框架,但我发现很难看出哪些是实际使用和维护的。

mwa*_*wal 1

我通过改回他的来解决这个问题:

(defun start-blogdemo (&optional (port 8080))
  (start '#:blogdemo :port port :render-method 'html-frame))  
Run Code Online (Sandbox Code Playgroud)

到:

(defun start-blogdemo (&optional (port 8080))
  (start '#:blogdemo :port port))
Run Code Online (Sandbox Code Playgroud)

util.lisp

然后你需要让你的每条路线都blogdemo.lisp不像:

(define-route home ("")
  (list :title "Blogdemo"
        :body (mapcar #'render-post *posts*)))
Run Code Online (Sandbox Code Playgroud)

但相反,像:

(define-route home ("")
  (html-frame
    (list :title "Blogdemo"
          :body (mapcar #'render-post *posts*))))
Run Code Online (Sandbox Code Playgroud)

这个解决方案的起源是我并不完全理解他所做的抽象的正确性(并且在 p37 上争论了很多,他也在此处讨论了),所以我颠倒了它并且它起作用了。


另请注意,路由add应如下所示(表单:requirement需要位于 html-frame 之前,后者是最后一个表单,因此是返回值)。

(define-route add ("add")
  (:requirement #'logged-on-p)
  (html-frame
    (list :title "Add a blog post"
          :body (add-post-form))))
Run Code Online (Sandbox Code Playgroud)

同样,:sift-variables 表单也应该排在author&post路线的前面,就像 一样:requirement。那么整个应用程序应该适合您。