Hunchentoot调度员
Hunchentoot dispatcher
我对 Common Lisp (SBCL) 和 Hunchentoot(使用 Quicklisp)比较陌生。有人能告诉我如何让它工作吗?我正在尝试将一个 Hunchentoot 服务器和一些路径作为一个单元包装在一个函数中。当我 运行 这样做时,只有 Hunchentoot 的索引页面可用,路径 /a 和 /b 不可用。
(defun app0 (port)
(let ((*dispatch-table* nil) (server (make-instance 'hunchentoot:acceptor :port port)))
(push (hunchentoot:create-prefix-dispatcher "/a" (lambda () "a")) *dispatch-table*)
(push (hunchentoot:create-prefix-dispatcher "/b" (lambda () "b")) *dispatch-table*)
(hunchentoot:start server) server))
据我所知,存在多个问题。首先,通过 *dispatch-table*
进行的请求处理要求接受器的类型为 easy-acceptor
,即您必须
(make-instance 'easy-acceptor ...)
documentation有详细内容
第二个问题是,您在设置代码期间重新绑定 *dispatch-table*
,并将新值推送到此绑定中。由于绑定在 let
完成后恢复(并且由于 hunchentoot:start
异步工作),当服务器 运行 时,您在 *dispatch-table*
中的条目实际上丢失了。尝试
(push (hunchentoot:create-prefix-dispatcher "/a" (lambda () "a")) *dispatch-table*)
(push (hunchentoot:create-prefix-dispatcher "/b" (lambda () "b")) *dispatch-table*)
在顶层(或在专用设置函数中做类似的事情)。如果你不喜欢全局 *dispatch-table*
方法,你也可以创建一个 acceptor
的子类,并覆盖 acceptor-dispatch-request
(因此,实现你喜欢的任何类型的调度)。
作为旁注:您没有为 *dispatch-table*
添加前缀,而实际上您为 hunchentoot
包中的任何其他符号添加前缀。这只是一个 copy/paste 错误,还是在您的实际代码中也是如此?如果您不 :use
hunchentoot
包在您的代码恰好存在的任何包中,那么您还必须将调度 table 限定为 hunchentoot:*dispatch-table*
.
编辑(解决评论区的问题)有一个example in the hunchentoot documentation,它似乎做的正是你想做的:
(defclass vhost (tbnl:acceptor)
((dispatch-table
:initform '()
:accessor dispatch-table
:documentation "List of dispatch functions"))
(:default-initargs
:address "127.0.0.1"))
(defmethod tbnl:acceptor-dispatch-request ((vhost vhost) request)
(mapc (lambda (dispatcher)
(let ((handler (funcall dispatcher request)))
(when handler
(return-from tbnl:acceptor-dispatch-request (funcall handler)))))
(dispatch-table vhost))
(call-next-method))
(defvar vhost1 (make-instance 'vhost :port 50001))
(defvar vhost2 (make-instance 'vhost :port 50002))
(push
(tbnl:create-prefix-dispatcher "/foo" 'foo1)
(dispatch-table vhost1))
(push
(tbnl:create-prefix-dispatcher "/foo" 'foo2)
(dispatch-table vhost2))
(defun foo1 () "Hello")
(defun foo2 () "Goodbye")
(tbnl:start vhost1)
(tbnl:start vhost2)
(为简洁起见删除了文档中的注释)。 tbnl
是包 hunchentoot
的预定义昵称。您可以互换使用两者,但我建议您选择一个并坚持使用。将两者混合可能会造成混淆。
我对 Common Lisp (SBCL) 和 Hunchentoot(使用 Quicklisp)比较陌生。有人能告诉我如何让它工作吗?我正在尝试将一个 Hunchentoot 服务器和一些路径作为一个单元包装在一个函数中。当我 运行 这样做时,只有 Hunchentoot 的索引页面可用,路径 /a 和 /b 不可用。
(defun app0 (port)
(let ((*dispatch-table* nil) (server (make-instance 'hunchentoot:acceptor :port port)))
(push (hunchentoot:create-prefix-dispatcher "/a" (lambda () "a")) *dispatch-table*)
(push (hunchentoot:create-prefix-dispatcher "/b" (lambda () "b")) *dispatch-table*)
(hunchentoot:start server) server))
据我所知,存在多个问题。首先,通过 *dispatch-table*
进行的请求处理要求接受器的类型为 easy-acceptor
,即您必须
(make-instance 'easy-acceptor ...)
documentation有详细内容
第二个问题是,您在设置代码期间重新绑定 *dispatch-table*
,并将新值推送到此绑定中。由于绑定在 let
完成后恢复(并且由于 hunchentoot:start
异步工作),当服务器 运行 时,您在 *dispatch-table*
中的条目实际上丢失了。尝试
(push (hunchentoot:create-prefix-dispatcher "/a" (lambda () "a")) *dispatch-table*)
(push (hunchentoot:create-prefix-dispatcher "/b" (lambda () "b")) *dispatch-table*)
在顶层(或在专用设置函数中做类似的事情)。如果你不喜欢全局 *dispatch-table*
方法,你也可以创建一个 acceptor
的子类,并覆盖 acceptor-dispatch-request
(因此,实现你喜欢的任何类型的调度)。
作为旁注:您没有为 *dispatch-table*
添加前缀,而实际上您为 hunchentoot
包中的任何其他符号添加前缀。这只是一个 copy/paste 错误,还是在您的实际代码中也是如此?如果您不 :use
hunchentoot
包在您的代码恰好存在的任何包中,那么您还必须将调度 table 限定为 hunchentoot:*dispatch-table*
.
编辑(解决评论区的问题)有一个example in the hunchentoot documentation,它似乎做的正是你想做的:
(defclass vhost (tbnl:acceptor)
((dispatch-table
:initform '()
:accessor dispatch-table
:documentation "List of dispatch functions"))
(:default-initargs
:address "127.0.0.1"))
(defmethod tbnl:acceptor-dispatch-request ((vhost vhost) request)
(mapc (lambda (dispatcher)
(let ((handler (funcall dispatcher request)))
(when handler
(return-from tbnl:acceptor-dispatch-request (funcall handler)))))
(dispatch-table vhost))
(call-next-method))
(defvar vhost1 (make-instance 'vhost :port 50001))
(defvar vhost2 (make-instance 'vhost :port 50002))
(push
(tbnl:create-prefix-dispatcher "/foo" 'foo1)
(dispatch-table vhost1))
(push
(tbnl:create-prefix-dispatcher "/foo" 'foo2)
(dispatch-table vhost2))
(defun foo1 () "Hello")
(defun foo2 () "Goodbye")
(tbnl:start vhost1)
(tbnl:start vhost2)
(为简洁起见删除了文档中的注释)。 tbnl
是包 hunchentoot
的预定义昵称。您可以互换使用两者,但我建议您选择一个并坚持使用。将两者混合可能会造成混淆。