【问题标题】:How to use http.kit server with drawbridge ring handler?如何将 http.kit 服务器与吊桥环处理程序一起使用?
【发布时间】:2015-08-07 20:32:08
【问题描述】:

我有以下服务器代码:

(ns tweet-sentiment.server
(:require [clojure.java.io :as io]
            [tweet-sentiment.dev :refer [is-dev? inject-devmode-html browser-repl start-figwheel start-less]]
            [compojure.core :refer [GET POST defroutes]]
            [compojure.route :refer [resources]]
            [net.cgrand.enlive-html :refer [deftemplate]]
            [net.cgrand.reload :refer [auto-reload]]
            [ring.middleware.reload :as reload]
            [ring.middleware.defaults :refer [wrap-defaults api-defaults]]
            [tweet-sentiment.utils :refer [generate-response]]
            [environ.core :refer [env]]
            [org.httpkit.server :refer [run-server]]
            [ring.middleware.edn :refer [wrap-edn-params]]
            [tweet-sentiment.tweets :refer [tweets]]
            [tweet-sentiment.dandelion :refer [dandelion-sentiment]]
            [clojure.core.async :refer [>!! <!! put! take! pipe chan]]
            [cemerick.drawbridge :as drawbridge]
            [ring.middleware.basic-authentication :refer [wrap-basic-authentication]]
            )
  (:gen-class))

(defonce server (atom nil))

(deftemplate page (io/resource "index.html") []
             [:body] (if is-dev? inject-devmode-html identity))

(defroutes routes
           (resources "/")
           (resources "/react" {:root "react"})
           (GET "/*" req (page)))


(defn wrap-drawbridge [handler]
  (fn [req]
    (if (= "/repl" (:uri req))
      (drawbridge/ring-handler req)
      (handler req))))

(def http-handler
  (if is-dev?
    (-> #'routes
        (wrap-defaults api-defaults)
        reload/wrap-reload
        wrap-edn-params
        wrap-drawbridge)

    (-> (wrap-defaults #'routes api-defaults)
        wrap-edn-params
        wrap-drawbridge)))

(defn run-web-server [& [port]]
  (let [port (Integer. (or port (env :port) 10555))]
    (println (format "Starting web server on port %d." port))
    (reset! server (run-server http-handler {:port port :join? false}))))

(defn run-auto-reload [& [port]]
  (auto-reload *ns*)
  (start-figwheel)
  (start-less))

(defn run [& [port]]
  (when is-dev?
    (run-auto-reload))
  (run-web-server port))

(defn stop-server []
  (when-not (nil? @server)
    (@server :timeout 0)
    (reset! server nil)))

(defn restart-server []
  (stop-server)
  (run-web-server))

(defn -main [& [port]]
  (run port))

当我尝试以开发者或生产者身份连接到吊桥 REPL 时:

lein repl :connect http://localhost:10555/repl

我收到以下错误:

ERROR - POST /repl
java.lang.IllegalArgumentException: No value supplied for key: {:remote-addr "127.0.0.1", :headers {"accept-encoding" "gzip, deflate", "connection" "close", "content-length" "48", "content-type" "application/x-www-form-urlencoded", "host" "localhost:10555", "user-agent" "Apache-HttpClient/4.3.3 (java 1.5)"}, :async-channel #<AsyncChannel /127.0.0.1:10555<->/127.0.0.1:60374>, :server-port 10555, :content-length 48, :websocket? false, :content-type "application/x-www-form-urlencoded", :character-encoding "utf8", :uri "/repl", :server-name "localhost", :query-string nil, :body #<BytesInputStream BytesInputStream[len=48]>, :scheme :http, :request-method :post}
    at clojure.lang.PersistentHashMap.create(PersistentHashMap.java:77)
    at cemerick.drawbridge$ring_handler.doInvoke(drawbridge.clj:49)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at tweet_sentiment.server$wrap_drawbridge$fn__21884.invoke(server.clj:36)
    at org.httpkit.server.HttpHandler.run(RingHandler.java:91)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

问题显然出在drawbridge/ring-handler 函数中。 这些是我的依赖项:

[[org.clojure/clojure "1.6.0"]
                 [org.clojure/clojurescript "0.0-3058" :scope "provided"]
                 [ring "1.3.2"]
                 [ring/ring-defaults "0.1.4"]
                 [compojure "1.3.2"]
                 [enlive "1.1.6"]
                 [org.omcljs/om "0.8.8"]
                 [om-sync "0.1.1"]
                 [environ "1.0.0"]
                 [http-kit "2.1.19"]
                 [fogus/ring-edn "0.3.0"]
                 [prismatic/om-tools "0.3.11"]
                 [secretary "1.2.3"]
                 [sablono "0.3.4"]
                 [twitter-api "0.7.8"]
                 [racehub/om-bootstrap "0.5.3"]
                 [cheshire "5.2.0"]
                 [com.cemerick/drawbridge "0.0.7"]
                 [ring-basic-authentication "1.0.1"]]

有没有人使用 drawbrige 获得工作 http.kit 服务器?我错过了什么?

【问题讨论】:

    标签: clojure ring http-kit


    【解决方案1】:

    我终于想通了,服务器文件应该看起来像这样

    (ns tweet-sentiment.server
      (:require [clojure.java.io :as io]
                [tweet-sentiment.dev :refer [is-dev? inject-devmode-html browser-repl start-figwheel start-less]]
                [compojure.core :refer [GET POST defroutes]]
                [compojure.route :refer [resources]]
                [net.cgrand.enlive-html :refer [deftemplate]]
                [net.cgrand.reload :refer [auto-reload]]
                [ring.middleware.reload :as reload]
                [ring.middleware.defaults :refer [wrap-defaults api-defaults]]
                [tweet-sentiment.utils :refer [generate-response]]
                [environ.core :refer [env]]
                [org.httpkit.server :refer [run-server]]
                [ring.middleware.edn :refer [wrap-edn-params]]
                [clojure.core.async :refer [>!! <!! put! take! pipe chan]]
                [cemerick.drawbridge :as drawbridge]
                [ring.middleware.basic-authentication :refer [wrap-basic-authentication]]
                [ring.middleware.params :as params]
                [ring.middleware.keyword-params :as keyword-params]
                [ring.middleware.nested-params :as nested-params]
                [ring.middleware.session :as session]
                )
      (:gen-class))
    
    (defonce server (atom nil))
    
    (deftemplate page (io/resource "index.html") []
                 [:body] (if is-dev? inject-devmode-html identity))
    
    (defroutes routes
               (resources "/")
               (resources "/react" {:root "react"})
               (GET "/*" req (page)))
    
    (defn authenticated? [name pass]
      (= [name pass] [(System/getenv "AUTH_USER") (System/getenv "AUTH_PASS")]))
    
    (def drawbridge-handler
      (-> (drawbridge/ring-handler)
          (keyword-params/wrap-keyword-params)
          (nested-params/wrap-nested-params)
          (params/wrap-params)
          (session/wrap-session)))
    
    (defn http-handler [handler]
      (-> handler
          (wrap-defaults api-defaults)
          wrap-edn-params))
    
    (defn wrap-http [handler]
      (fn [req]
        (let [handler (if (= "/repl" (:uri req))
                        (wrap-basic-authentication drawbridge-handler authenticated?)
                        (if is-dev?
                          (-> handler
                              http-handler
                              reload/wrap-reload)
                          (-> handler
                              http-handler)))]
          (handler req))))
    
    (defn run-web-server [& [port]]
      (let [port (Integer. (or port (env :port) 10555))]
        (println (format "Starting web server on port %d." port))
        (reset! server
                (run-server (wrap-http #'routes) {:port port :join? false})
                )))
    
    (defn run-auto-reload [& [port]]
      (auto-reload *ns*)
      (start-figwheel)
      (start-less))
    
    (defn run [& [port]]
      (when is-dev?
        (run-auto-reload))
      (run-web-server port))
    
    (defn stop-server []
      (when-not (nil? @server)
        (@server :timeout 0)
        (reset! server nil)))
    
    (defn restart-server []
      (stop-server)
      (run-web-server))
    
    (defn -main [& [port]]
      (run port))
    

    【讨论】:

    • 这个问题和答案很有帮助,因为我可以研究它并最终发现我的错误,但也许总结也很有用。您需要做的是: - 将吊桥的环处理程序包装在适当的包装器中(参见上面的吊桥处理程序功能) - 将其放入 wrap-basic-authentication - 不要用更多的东西包装它。做一个非此即彼的。应用程序或吊桥repl。也就是说,让 wrap-drawbridge 成为最后一个!这对我有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-05
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    相关资源
    最近更新 更多