Hunchentoot重定向列表

时间:2016-04-10 19:05:00

标签: common-lisp hunchentoot

我网站的URI结构最近发生了巨大变化,我需要将所有旧页面重定向到相应的新页面。我有一个所有旧URI和新URI对的虚线列表。目前我正在尝试为循环中的每个定义简单的处理程序:

(let ((redirects '(("/old/uri/example-1" . "/new/uri/example-1"))))
  (dolist (redirect redirects)
    (hunchentoot:define-easy-handler (???? :uri (first redirect)) ()
       (redirect (rest redirect)))
    ))

也许有更好的方法。假设define-easy-handler是正确的,它需要每个简单处理程序的函数符号。我尝试了以下无济于事:

  1. 将(gensym)放置在需要函数符号
  2. 的位置
  3. 使用列表而非虚线列表并调用(首次重定向)所需的符号
  4. 在整个事物周围放置一个quasiquote和一个unquote(第一次重定向)
  5. 实现这一目标的好方法是什么?

2 个答案:

答案 0 :(得分:1)

虽然你已经解决了这个问题,但我认为我可以将其作为替代方案添加。如果您不想制作完整的自定义接受器,则可以HUNCHENTOOT:ACCEPTOR-DISPATCH-REQUESTHUNCHENTOOT:EASY-HANDLER添加around方法。

让我们先制作一个接受者和一页:

(defparameter *acceptor* (make-instance 'hunchentoot:easy-acceptor :port 4242))

(hunchentoot:define-easy-handler (foo :uri "/foo") ()
  (format nil "<html><body><h1>Test</h1><p>foo</p></body></html>"))

(hunchentoot:start *acceptor*)

然后将/bar/quux重定向到/foo

;; A simple helper to create prefix dispatchers.
(defun make-redirect-list (redirects)
  (mapcar (lambda (redirect)
            (destructuring-bind (from . to) redirect
              (hunchentoot:create-prefix-dispatcher from
                                                    (lambda ()
                                                      (hunchentoot:redirect to)))))
          redirects))

(defparameter *redirects* (make-redirect-list
                           '(("/bar" . "/foo")
                             ("/quux" . "/foo"))))

(defmethod hunchentoot:acceptor-dispatch-request :around
    ((acceptor hunchentoot:easy-acceptor) request)
  (dolist (redirect *redirects*)
    ;; Match the request against the prefix dispatchers in *REDIRECTS*...
    (let ((handler (funcall redirect request)))
      (when handler
        ;; and call the corresponding handler if a match is found.
        (return-from hunchentoot:acceptor-dispatch-request
          (funcall handler)))))
    ;; Unless a handler was found, call next method to 
    ;; handle the request normally.
  (call-next-method))

编辑:使用around方法而不是之前。我最初认为,让它通常调用main方法对于任何日志/等都是必要的。发生在那里,但经过进一步的测试似乎没有。

答案 1 :(得分:0)

此解决方案有效。我非常感谢有关这是否是最佳做法的反馈。

(defun add-redirect (name from to)
  (eval `(hunchentoot:define-easy-handler (,name :uri ,from) ()
    (redirect ,to))))

(defun add-redirects (redirects)
  (dolist (redirect redirects)
    (add-redirect (first redirect) (second redirect) (third redirect))
    ))

(add-redirects
 '(
   (redirect-1 "/redirect-1/" "/destination-1/")
   (redirect-2 "/redirect-2/" "/destination-2/")
   (redirect-3 "/redirect-3/" "/destination-3/")
   ))