Hunchentoot通过HTTP方法调度

时间:2013-09-27 23:50:35

标签: common-lisp sbcl hunchentoot

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

3 个答案:

答案 0 :(得分:4)

允许{(1}}参数(可能略带名称){1}}参数是请求对象上的字符串或谓词。因此,您可以在那里传递一个函数来检查方法和路径是否匹配。我写了一个宏来让它更漂亮:

:uri

在找到路径但方法不是的情况下,我们应该返回HTTP 405错误,而不是Hunchentoot在没有处理程序匹配时返回的404错误。为此,您可以为您定义的每个路径手动编写一个catch-all处理程序。 405响应应该包含一个可接受的方法列表,我想不出一个简单的方法来生成一个简单的修改(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!") 来直接支持方法的专业化,这可能是一个好主意。

答案 1 :(得分: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
  )

答案 2 :(得分: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))