Clojure/Ring/Jetty:我正在使用lein ring server。如何配置被实例化的Jetty实例?

10

当我直接调用Jetty处理程序时,我可以像这样传递一个配置器:

(def header-buffer-size 8388608)
(defn start [port]
  (ring/run-jetty
   (var app)
   {:port port
    :join? false
    :host "127.0.0.1"
    :configurator
    (fn [jetty]
      (doseq [connector (.getConnectors jetty)]
        (.setHeaderBufferSize connector header-buffer-size)))}))

我不得不这样做,因为在发布时我一直收到“FULL HEAD”错误。现在,我重新设计了使用lein ring server直接调用的事情。

> lein ring server

这使用了我项目.clj文件中指定的一些配置:

:ring {:handler caribou.api.core/app
       :servlet-name "caribou-api"
       :init caribou.api.core/init
       :port 33443}

这个很有效,但是现在我又遇到了完整标题的问题。所以我尝试在其中添加一个配置器:

:ring {:handler caribou.api.core/app
       :servlet-name "caribou-api"
       :init caribou.api.core/init
       :configurator
       (fn [jetty]
         (doseq [connector (.getConnectors jetty)]
           (.setHeaderBufferSize connector 8388608)))
       :port 33443})

并且会产生以下堆栈跟踪:

Exception in thread "main" java.lang.ClassCastException: 
clojure.lang.PersistentList cannot be cast to clojure.lang.IFn
  at ring.adapter.jetty$run_jetty.invoke(jetty.clj:66)
  at ring.server.standalone$serve$fn__833.invoke(standalone.clj:78)
  at ring.server.standalone$try_port.invoke(standalone.clj:12)
  at ring.server.standalone$serve.doInvoke(standalone.clj:75)
  at clojure.lang.RestFn.invoke(RestFn.java:423)
  at ring.server.leiningen$serve.invoke(leiningen.clj:20)

我想这和直接将函数放在地图中有关,所以我将其定义在项目之外(caribou.api.core),并尝试像引用其他在别处定义的函数一样引用它:

;; in caribou/api/core.clj
(def header-buffer-size 8388608)
(defn full-head-avoidance
  [jetty]
  (doseq [connector (.getConnectors jetty)]
    (.setHeaderBufferSize connector header-buffer-size)))

;; in project.clj
:ring {:handler caribou.api.core/app
       :servlet-name "caribou-api"
       :init caribou.api.core/init
       :configurator caribou.api.core/full-head-avoidance
       :port 33443})

我已经运行了这个应用,但在提交时仍然遇到了 413:FULL HEAD 错误。有什么想法吗?谢谢!

2个回答

4

defproject 表单内的内容默认不会被评估,但是当需要时可以在 defproject 中使用 ~(取消引用)来进行:

(defproject foo "1.2.3"
  ...
  :some-fn-key ~(fn [& args] ...))

在这种情况下,您需要取消引用定义配置器函数的fn表单(如果不取消引用,则将其作为包含一堆符号的列表使用,而不是编译成函数)。
或者,您可以在defproject表单外定义配置器并在defproject内引用其名称,如您的第二种方法,但是然后您需要取消引用defproject内的名称 - 否则它将被视为符号。请注意,在后一种情况下不会产生异常,因为符号实际上是可调用的,并接受任意参数(但只在使用除映射或集合以外的内容调用时返回nil;对于映射或集合,它们在其参数中查找自身)。

这可能是因为回答发布后发生了变化,但当我像这里所建议的那样(取消引用函数定义)时,我会得到另一个错误:“对象标记没有读取函数”。您知道为什么会出现这种情况吗? - Tim

3
答案是不使用环形服务器,直接使用ring/ring-jetty-adapter启动jetty即可。这样我仍然可以传递配置器,BTW已经更改为以下内容:
(defn full-head-avoidance
  [jetty]
  (doseq [connector (.getConnectors jetty)]
    (.setRequestHeaderSize connector header-buffer-size)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接