标签: ring

如何在clojure中停止jetty服务器?

我正在使用ring和clojure编写Web应用程序.我使用jetty适配器开发服务器和emacs/SLIME for IDE.虽然wrap-reload确实有帮助,但run-jetty会阻止我的粘贴会话,我希望能够随意启动/停止它,而无需在单独的终端会话中运行它.理想情况下,我想定义一个服务器代理和函数start-server和stop-server,它们将启动/停止代理中的服务器.这可能吗?

jetty clojure ring

53
推荐指数
1
解决办法
1万
查看次数

具有不同中间件的Compojure路由

我目前正在使用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)

middleware routes clojure compojure ring

38
推荐指数
3
解决办法
8599
查看次数

我可以使用http-kit和core.async创建一个完全无阻塞的后端应用程序吗?

我想知道是否可以使用http-kit整合一个完全无阻塞的Clojure后端Web应用程序.

(实际上任何与Ring兼容的http服务器都没关系;我提到了http-kit,因为它声称有一个事件驱动的非阻塞模型).


编辑:TL; DR

这个问题是我对非阻塞/异步/事件驱动系统性质的一些误解的症状.如果你和我在同一个地方,这里有一些澄清.

只有当所有(例如,大多数)IO从头开始以非阻塞方式处理时,才能使事件驱动系统具有非阻塞的性能优势(如在Node.js中).这意味着所有数据库驱动程序,HTTP服务器和客户端,Web服务等都必须首先提供异步接口.特别是:

  • 如果您的数据库驱动程序提供同步接口,则无法使其成为非阻塞.(您的线程被阻止,无法检索它).如果你想要非阻塞,你需要使用其他东西.
  • 像core.async这样的高级协调实用程序无法使系统无阻塞.它们可以帮助您管理非阻塞代码,但不启用它.
  • 如果您的IO驱动程序是同步的,您可以使用core.async来获得异步的设计优势,但是您将无法获得它的性能优势.您的线程仍将浪费时间等待每个响应.

现在,具体来说:

  • 作为HTTP服务器的http-kit提供了非阻塞的异步接口.见下文.
  • 但是,许多Ring中间件由于它们基本上是同步的,因此与这种方法不兼容.基本上,任何更新返回响应的Ring中间件都不可用.

如果我做对了(我不是专家,所以请告诉我,如果我正在做错误的假设),Web应用程序的这种非阻塞模型的原则如下:

  1. 有一些超快的OS线程处理所有CPU密集型计算; 这些绝对不能等待.
  2. 有很多"弱线程"处理IO(数据库调用,Web服务调用,休眠等); 这些主要是为了等待.
  3. 这是有益的,因为在处理请求上花费的等待时间通常是2(磁盘访问)到5(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)

clojure nonblocking ring core.async http-kit

35
推荐指数
1
解决办法
4832
查看次数

为什么Ring中间件的顺序需要颠倒?

我正在为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)

有用.

有人可以解释为什么你必须颠倒中间件的顺序?

clojure ring

16
推荐指数
3
解决办法
3375
查看次数

使用ring/compojure提供静态文件 - 来自战争

使用ring(以及lein-ring工具) - 我可以在开发中运行时根据文档提供来自"资源"等的静态文件 - 但是 - 当我通过lien uberwar打包时,我不知道如何制作它在容器中运行时提供这些文件.我在wrap-resource上看到了冲突的文档,或者设置了:resource-path但是似乎都没有.

clojure compojure ring leiningen

15
推荐指数
2
解决办法
1万
查看次数

在clojure/ring中,如何删除cookie?

假设我想删除一个cookie(例如,ring的会话cookie):

制作这样的响应地图:

{:cookies {"ring-session" {:value "kill", :max-age 1}}}
Run Code Online (Sandbox Code Playgroud)

似乎工作,但感觉有点hacky.

是否有一种干净的方式来删除它?

cookies session web-applications clojure ring

14
推荐指数
1
解决办法
1756
查看次数

使用Ring和Compojure为不同的中间件提供app和api路由

我有一个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 ring

14
推荐指数
1
解决办法
2185
查看次数

如何在Clojure/Compojure/Ring中将地图转换为URL查询字符串?

在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中有没有任何实用方法呢?

clojure compojure ring

13
推荐指数
2
解决办法
3483
查看次数

将状态作为参数传递给环处理程序?

如何最方便地将状态注入环处理程序(不使用全局变量)?

这是一个例子:

(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 函数完成类似的操作吗?

dependency-injection clojure compojure ring

13
推荐指数
1
解决办法
1265
查看次数

设置Ring-Anti-Forgery CSRF标头令牌

我试图通过在标题中设置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)

middleware header clojure csrf ring

13
推荐指数
1
解决办法
6220
查看次数