我正在使用ring和clojure编写Web应用程序.我使用jetty适配器开发服务器和emacs/SLIME for IDE.虽然wrap-reload确实有帮助,但run-jetty会阻止我的粘贴会话,我希望能够随意启动/停止它,而无需在单独的终端会话中运行它.理想情况下,我想定义一个服务器代理和函数start-server和stop-server,它们将启动/停止代理中的服务器.这可能吗?
我目前正在使用Compojure(以及Ring和相关的中间件)在Clojure中编写API.
我正在尝试根据路由应用不同的身份验证代码.请考虑以下代码:
(defroutes public-routes
(GET "/public-endpoint" [] ("PUBLIC ENDPOINT")))
(defroutes user-routes
(GET "/user-endpoint1" [] ("USER ENDPOINT 1"))
(GET "/user-endpoint2" [] ("USER ENDPOINT 1")))
(defroutes admin-routes
(GET "/admin-endpoint" [] ("ADMIN ENDPOINT")))
(def app
(handler/api
(routes
public-routes
(-> user-routes
(wrap-basic-authentication user-auth?)))))
(-> admin-routes
(wrap-basic-authentication admin-auth?)))))
Run Code Online (Sandbox Code Playgroud)
这不能按预期工作,因为它wrap-basic-authentication实际上包装了路由,因此无论包装路由如何都会尝试它.具体来说,如果需要将请求路由到admin-routes,user-auth?仍将尝试(并失败).
我使出context到根在一个共同的基本路径部分航线,但它是一个相当的限制(下面的代码可能无法正常工作,它只是说明的想法):
(defroutes user-routes
(GET "-endpoint1" [] ("USER ENDPOINT 1"))
(GET "-endpoint2" [] ("USER ENDPOINT 1")))
(defroutes admin-routes
(GET "-endpoint" [] ("ADMIN ENDPOINT")))
(def app
(handler/api
(routes …Run Code Online (Sandbox Code Playgroud) 我想知道是否可以使用http-kit整合一个完全无阻塞的Clojure后端Web应用程序.
(实际上任何与Ring兼容的http服务器都没关系;我提到了http-kit,因为它声称有一个事件驱动的非阻塞模型).
这个问题是我对非阻塞/异步/事件驱动系统性质的一些误解的症状.如果你和我在同一个地方,这里有一些澄清.
只有当所有(例如,大多数)IO从头开始以非阻塞方式处理时,才能使事件驱动系统具有非阻塞的性能优势(如在Node.js中).这意味着所有数据库驱动程序,HTTP服务器和客户端,Web服务等都必须首先提供异步接口.特别是:
现在,具体来说:
如果我做对了(我不是专家,所以请告诉我,如果我正在做错误的假设),Web应用程序的这种非阻塞模型的原则如下:
从我所看到的,默认情况下,Play Framework(Scala)和Node.js(JavaScript)平台支持此模型,具有基于承诺的实用程序,用于以编程方式管理异步.
让我们尝试使用Compojure路由在基于Ring的clojure应用程序中执行此操作.我有一个通过调用my-handle函数构造响应的路由:
(defroutes my-routes
(GET "/my/url" req (my-handle req))
)
(def my-app (noir.util.middleware/app-handler [my-routes]))
(defn start-my-server! []
(http-kit/run-server my-app))
Run Code Online (Sandbox Code Playgroud)
在Clojure应用程序中管理异步的普遍接受的方式似乎是基于CSP,使用core.async库,我完全没问题.因此,如果我想接受上面列出的非阻塞原则,我将以my-handle这种方式实现:
(require '[clojure.core.async :as a])
(defn my-handle [req]
(a/<!!
(a/go ; `go` makes channels calls asynchronous, so I'm not …Run Code Online (Sandbox Code Playgroud) 我正在为Ring编写一些中间件,我真的很困惑为什么我必须颠倒中间件的顺序.
我找到了这篇博文,但它没有解释为什么我要扭转它.
以下是博客文章的快速摘录:
(def app
(wrap-keyword-params (wrap-params my-handler)))
Run Code Online (Sandbox Code Playgroud)
答复是:
{; Trimmed for brevity
:params {"my_param" "54"}}
Run Code Online (Sandbox Code Playgroud)
请注意,没有调用wrap关键字params,因为params hash还不存在.但是当你颠倒中间件的顺序时:
(def app
(wrap-params (wrap-keyword-params my-handler)))
{; Trimmed for brevity
:params {:my_param "54"}}
Run Code Online (Sandbox Code Playgroud)
有用.
有人可以解释为什么你必须颠倒中间件的顺序?
使用ring(以及lein-ring工具) - 我可以在开发中运行时根据文档提供来自"资源"等的静态文件 - 但是 - 当我通过lien uberwar打包时,我不知道如何制作它在容器中运行时提供这些文件.我在wrap-resource上看到了冲突的文档,或者设置了:resource-path但是似乎都没有.
假设我想删除一个cookie(例如,ring的会话cookie):
制作这样的响应地图:
{:cookies {"ring-session" {:value "kill", :max-age 1}}}
Run Code Online (Sandbox Code Playgroud)
似乎工作,但感觉有点hacky.
是否有一种干净的方式来删除它?
我有一个ring + compojure应用程序,我想应用不同的中间件,具体取决于路由是Web应用程序的一部分还是api的一部分(基于json).
我在堆栈溢出和其他论坛上找到了这个问题的一些答案,但这些答案似乎比我一直使用的解决方案更复杂.我想知道我是如何做的,以及我在解决方案中可能缺少的东西是否存在缺陷.我正在做的一个非常简化的版本
(defroutes app-routes
(GET "/" [req] dump-req)
(route/not-found "Not Found"))
(defroutes api-routes
(GET "/api" [req] dump-req))
(def app
(routes (-> api-routes
(wrap-defaults api-defaults))
(-> app-routes
(wrap-defaults site-defaults))))
Run Code Online (Sandbox Code Playgroud)
请注意,中间件比我在此处显示的更多.
我遇到的唯一"限制"是,由于app-routes有未找到的路由,它需要到达最后或者在找到api路由之前触发它.
这似乎比我发现的其他一些解决方案更简单,更灵活,似乎要么使用额外的条件中间件,例如ring.middleware.conditional,或者在我看来是更复杂的路由定义,其中有一个额外的defroutes层并且需要用任何"*"等来定义defroutes.
我怀疑在这里有一些微妙的东西,虽然我的方法似乎有效,但它会导致意外行为或导致某些情况等.
在Clojure/Compojure中,如何将地图转换为URL查询字符串?
{:foo 1 :bar 2 :baz 3}
Run Code Online (Sandbox Code Playgroud)
至
foo=1&bar=2&baz=3
Run Code Online (Sandbox Code Playgroud)
在compojure中有没有任何实用方法呢?
如何最方便地将状态注入环处理程序(不使用全局变量)?
这是一个例子:
(defroutes main-routes
(GET "/api/fu" [] (rest-of-the-app the-state)))
(def app
(-> (handler/api main-routes)))
Run Code Online (Sandbox Code Playgroud)
我想the-state进入compojure处理程序main-routes.状态可能类似于使用以下内容创建的地图:
(defn create-app-state []
{:db (connect-to-db)
:log (create-log)})
Run Code Online (Sandbox Code Playgroud)
在非环形应用程序中,我将在main函数中创建状态,并开始将其作为函数参数注入到应用程序的不同组件中.
在:init不使用全局变量的情况下,可以使用ring 函数完成类似的操作吗?
我试图通过在标题中设置X-CSRF-Token 来实现Ring-Anti-Forgery库.
由于我使用的是静态html文件,因此我发现内置的打嗝帮助器(它在表单中设置令牌)是无用的.
这是我第一次尝试使用Clojure进行Web开发,所以我猜我完全错过了那些有经验的人应该明白的东西.
README状态的说明:
中间件还在X-CSRF-Token和X-XSRF-Token头字段中查找令牌.可以使用:read-token选项进一步自定义此行为:
(defn get-custom-token [request]
(get-in request [:headers "x-forgery-token"]))
(def app
(-> handler
(wrap-anti-forgery {:read-token get-custom-token})
(wrap-session)))
Run Code Online (Sandbox Code Playgroud)
我已经将上面的内容添加到handler.clj而没有任何成功.
project.clj
(defproject hooktale "0.0.1"
:description "Hooktale iOS App Website"
:url "http://www.hooktale.com"
:repositories {"sonartype releases" "https://oss.sonatype.org/content/repositories/releases/"}
:source-paths ["src/clj" "src/cljs"]
:dependencies [[org.clojure/clojure "1.5.1"]
[org.clojure/clojurescript "0.0-2080"]
[org.clojure/java.jdbc "0.3.0-beta2"]
[compojure "1.1.6"]
[com.mchange/c3p0 "0.9.5-pre5"]
[org.postgresql/postgresql "9.3-1100-jdbc4"]
[ring-anti-forgery "0.3.0"]]
:plugins [[lein-ring "0.8.8"]
[lein-cljsbuild "1.0.1-SNAPSHOT"]]
:ring {:handler hooktale.handler/app}
:profiles {:dev {:plugins [[javax.servlet/servlet-api "2.5"]
[ring-mock "0.1.5"]]
:cljsbuild {:builds [{:source-paths ["src/cljs"]
:compiler {:optimizations …Run Code Online (Sandbox Code Playgroud) clojure ×10
ring ×10
compojure ×5
middleware ×2
cookies ×1
core.async ×1
csrf ×1
header ×1
http-kit ×1
jetty ×1
leiningen ×1
nonblocking ×1
routes ×1
session ×1