【问题标题】:Hunchentoot dispatch by HTTP methodHunchentoot 通过 HTTP 方法调度
【发布时间】:2013-09-27 23:50:34
【问题描述】:

我找不到任何关于如何基于 HTTP 方法(在同一个 uri 上)进行调度的文档。我得到的最接近的是:default-request-type 上的define-easy-handler ——但它似乎派发给后者,即使我使用 GET 方法:

(define-easy-handler (index :uri "/" :default-request-type :get) ()
  (log-message* :info "GET on index ------ ")
  (format nil "Hello World"))

(define-easy-handler (echo :uri "/" :default-request-type :post) ()
  (log-message* :info "POST on index ------ ")
  (format nil "~S" (raw-post-data :force-text t)))

【问题讨论】:

  • 从查看源代码来看,default-requiest-type 似乎只影响调用处理程序时考虑的“参数”。它不影响是否调用处理程序。所以看起来你是在自己实现它。
  • 感谢您为我寻找源代码 :) 我想我必须自己实现一些东西

标签: common-lisp sbcl hunchentoot


【解决方案1】:

:uri 参数(可能有点欺骗性地命名)可以是字符串或请求对象上的谓词。因此,您可以在那里传递一个函数来检查方法和路径是否匹配。我写了一个宏让它更漂亮:

(defmacro method-path (methods path)
  "Expands to a predicate the returns true of the Hunchtoot request
has a SCRIPT-NAME matching the PATH and METHOD in the list of METHODS.
You may pass a single method as a designator for the list containing
only that method."
  (declare
   (type (or keyword list) methods)
   (type string path))
  `(lambda (request)
     (and (member (hunchentoot:request-method* request)
                 ,(if (keywordp methods)
                      `'(,methods)
                      `',methods))
          (string= (hunchentoot:script-name* request)
                   ,path))))

(hunchentoot:define-easy-handler (get-handler :uri (method-path :get "/hello")) ()
  "hello!")

(hunchentoot:define-easy-handler (post-handler :uri (method-path (:post :put) "/hello")) ()
  "a post or a put!")

在找到路径但找不到方法的情况下,我们可能应该返回 HTTP 405 错误,而不是 Hunchentoot 在没有匹配的处理程序时返回的 404 错误。为此,您可以为您定义的每个路径手动编写一个包罗万象的处理程序。 405 响应应该包含一个可接受的方法列表,我想不出一种简单的方法来生成一个短的修改 define-easy-handler 以直接支持方法的专业化,这可能是个好主意。

【讨论】:

    【解决方案2】:

    许多建立在 hunchentoot 之上的框架都有这个。 RestasCaveman 只是两个例子。例如,在 Restas 中,您可以说:

    (restas:define-route foo ("/foo" :method :get)
      ; some code here
      )
    
    (restas:define-route foo/post ("/foo" :method :post)
      ; some other code here
      )
    

    【讨论】:

    • 感谢您的指点——我研究过使用 Caveman,但在此之后切换回 Hunchentoot issue
    【解决方案3】:

    我们现在有一个 Hunchentoot 插件可以做到这一点:easy-routes。它带来了 HTTP 方法的调度,从 url 路径中提取参数,以及一个方便的装饰符号。

    要使用它,我们只需要使用它的routes-acceptor 而不是默认的easy-acceptor

    (hunchentoot:start (make-instance 'easy-routes:routes-acceptor))
    

    一个例子:

    (defroute foo ("/foo/:arg1/:arg2" :method :get)
       (&get w)
        (format nil "<h1>FOO arg1: ~a arg2: ~a ~a</h1>" arg1 arg2 w))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多