clojure - 基座提前终止不起作用

标签 clojure pedestal

http://pedestal.io/reference/servlet-interceptor是这样说的

Before invoking the :enter functions, the servlet interceptor sets up a "terminator" predicate on the context. It terminates the interceptor chain when the context map returned by an interceptor has a response map attached.

我的服务器有这个:

(ns wp-server.server
  (:gen-class)                                              ; for -main method in uberjar
  (:require
    [io.pedestal.http :as server]
    [io.pedestal.http.route :as route]
    [wp-server.service :as service]
    [wp-server.datomic :as datomic]))

(defonce runnable-service (atom nil))

(defn -main
  "The entry-point for 'lein run'"
  [& args]
  (println "/nConnecting to datomic...")
  (datomic/connect!)
  (println "\nCreating your server...")
  (reset! runnable-service (server/create-servlet service/service))
  (server/start runnable-service))

(defn create-runnable-dev-service
  "The entry-point for 'lein run-dev'"
  [& args]
  (println "\nConnecting to [DEV] database...")
  (datomic/connect-dev!)
  (println "\nCreating your [DEV] server...")
  (-> service/service
      (merge {:env                     :dev
              ::server/join?           false
              ::server/routes          #(route/expand-routes (deref #'service/routes))
              ::server/allowed-origins {:creds true :allowed-origins (constantly true)}
              ::server/secure-headers  {:content-security-policy-settings {:object-src "none"}}})
      server/default-interceptors
      server/dev-interceptors
      server/create-servlet))


(defn start-dev []
  (when-not @runnable-service
    (reset! runnable-service (create-runnable-dev-service)))
  (server/start @runnable-service))

(defn stop-dev []
  (server/stop @runnable-service))

(defn restart-dev []
  (stop-dev)
  (start-dev))

我的服务如下所示:

(ns wp-server.service
  (:require
    [datomic.api :as d]
    [io.pedestal.http :as http]
    [io.pedestal.http.body-params :as body-params]
    [io.pedestal.http.route :as route]
    [ring.util.response :as ring-resp]
    [wp-server.datomic :as datomic]
    [wp-common.client :as wp-common-client]
    [wp-common.core :as wp-common-core]
    [clojure.spec.alpha :as s]
    [ring.util.response :as ring-response]))

(defn about-page
  [request]
  (ring-resp/response (format "Clojure %s - served from %s"
                              (clojure-version)
                              (route/url-for ::about-page))))

(def home-page
  {:name  :home-page
   :enter (fn [context]
            (prn "TWO")
            (assoc context :response {:status 200 :body "Hello, world!"}))})

(defn db-test-page
  [{:keys [:database]}]
  (ring-resp/response
    (prn-str
      (d/q '[:find ?text
             :where
             [?e :advisor/first-name ?text]]
           database))))

(def common-interceptors [datomic/db-interceptor (body-params/body-params) http/html-body])

(defn create-spec-validator
  [spec]
  {:name :validate-spec
   :enter
         (fn [{{:keys [:edn-params]} :request :as context}]
           (prn "ONE")
           (if-let [explained (s/explain-data spec edn-params)]
             (assoc context
               :response {:status 400 :body explained})))})


(def routes #{
              ;["/" :get (conj common-interceptors `home-page)]
              ["/clients" :post (conj common-interceptors (create-spec-validator ::wp-common-client/schema) home-page)]
              ["/db-test" :get (conj common-interceptors `db-test-page)]
              ["/about" :get (conj common-interceptors `about-page)]})

(def service {:env                     :prod
              ::http/routes            routes
              ::http/type              :jetty
              ::http/port              5000
              ::http/container-options {:h2c? true
                                        :h2?  false
                                        :ssl? false}})

当向 localhost:5000/clients 发送请求时,其主体未通过规范,create-spec-validator 拦截器会向上下文添加响应。我通过在主页拦截器中记录上下文来确认这一点。我希望按照文档跳过主页拦截器。这不会发生。相反,会调用主页拦截器的 :enter 函数并覆盖响应。

当前面的 create-spec-validator 返回带有响应的上下文时,为什么主页拦截器不会被跳过?

最佳答案

如果您找到终止代码,它会调用

(defn response?
  "True if the supplied value is a valid response map."
  {:added "1.1"}
  [resp]
  (and (map? resp)
       (integer? (:status resp))
       (map? (:headers resp))))

测试 :response 中是否存在有效响应映射。尝试在响应中的 :headers 中设置一个空映射:然后它应该终止。

当然,理想情况下,您会将 Content-Type 设置为有意义的内容。

关于clojure - 基座提前终止不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48198671/

相关文章:

dictionary - 在 Clojure 中如何创建 "add id to map"函数?

clojure.spec conform 抛出堆栈溢出异常

object - Clojure并发: Let an agent act on a java object/deftype

clojure - 以多种语法引用形式重用 auto-gensym 的宏

clojure - 从对 Pedestal 的 POST 请求获取 POST 正文数据

clojure:使用 korma 动态组合查询

clojure - SSE 订阅者 - 分布在多个服务器上?

proxy - 如何将部分请求转发到 Clojure 中的另一台服务器?

clojure - 命名空间未加载到 clojure 基座中

Clojure ^在命名空间中共享