5

我找不到任何关于如何基于 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)))
4

3 回答 3

4

(可能有点欺骗性地命名):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以直接支持方法专业化的方法,这可能是一个好主意。

于 2014-10-18T13:08:46.543 回答
3

许多建立在 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
  )
于 2013-10-11T16:28:27.693 回答
0

我们现在有一个 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))
于 2019-10-16T10:44:48.567 回答