【问题标题】:Understanding handlers on Ring and Appengine-magic (Clojure)了解 Ring 和 Appengine-magic (Clojure) 上的处理程序
【发布时间】:2011-05-26 21:46:39
【问题描述】:
我开始开发一些 clojure 网络应用程序,并决定使用 Ring + Compojure 的组合。
最近我决定用 AppEngine-magic (https://github.com/gcv/appengine-magic) 试试 Google Appengine。然而,appengine-magic(通过它的 start 函数)和 ring 的 run-jetty 函数都只需要 1 个处理程序作为参数,我正在实现几个处理程序并想知道如何部署它们。
提前致谢,
泽
【问题讨论】:
标签:
http
google-app-engine
clojure
httpwebrequest
ring
【解决方案1】:
总是只有一个顶级处理程序——毕竟,即使在某个概念级别有多个处理程序,应用程序也需要以某种方式决定将哪个处理程序应用于给定的请求,因此生成的例程选择成为顶级处理程序。因此,简短的回答是您需要提供一个函数,该函数将查看请求并将其交给应用程序内的多个处理程序中的适当处理程序;该函数是要提供给run-jetty(或等效项)的处理程序。
通常使用 Ring + Compojure,您将拥有一些用于处理特定 URI 的基本(“内部”)处理程序和一些作为中间件实现的特殊用途处理程序(例如,用于 404)。前者倾向于以defroutes 形式定义,而后者是高阶函数。
中间件处理程序在查看请求后自行决定是要立即返回响应还是委托给它们所包裹的处理程序。为适当的 URI 调用基于路由的“内部”处理程序,并且可以选择返回 nil 以指示请求对它们没有意义(此时尝试剩余的基于路由的处理程序;如果所有nil out,最终响应通常是由某个中间件生成的,可能返回 404)。
我写了一篇关于 Compojure here 的冗长答案;也许它可能有助于了解 Compojure 的基于路由的处理程序定义。
【解决方案2】:
我不知道这是否是最好的方法,我最终实现了一个 ring.middleware 函数,它将其他处理程序包装在主要的处理程序周围:
(defn wrap-ohandler [f handler]
(fn [req]
(let [ res (f req) ]
(if (= res nil) (handler req) res))))
(def handler-wrapped
(-> #'main-handler
(wrap-ohandler #'anotherhandler )
(wrap-stacktrace)
(wrap-params)))
这可行,但这是一个好方法吗?