当基座中允许原点时,不存在 'Access-Control-Allow-Origin' header

No 'Access-Control-Allow-Origin' header is present when origin is allowed in Pedestal

当我尝试从 cljs 应用请求资源时(运行在 http://localhost:3000) to my Pedestal server (running on http://localhost:8080) I get the below error. I would like to allow CORS from http://localhost:3000 上:

XMLHttpRequest cannot load http://localhost:8080/db/query. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.

我正在使用 cljs-http 从客户端发送请求。请求看起来像这样:

(defn load-server-data
  []
  (go
    (let [q (<! (http/post "http://localhost:8080/db/query"
                           {:edn-params {:query '[:find ?rep ?last
                                                  :where
                                                  [?rep :sales-rep/first-name ?last]]}}))]
      (println "q" q))))

/db/query 的路线如下所示:

(defroutes routes
           [[["/db"
              {:post handlers/db-post}
              ["/query" {:post handlers/db-query}
               ^:interceptors [interceptors/edn-interceptor]]]]])

这是 /db/query 的处理程序:

(defn db-query
  [req]
  (let [edn-params (:edn-params req)
        q (:query edn-params)
        args (:args edn-params)
        q-result (apply d/q q (d/db conn) args)]
    {:status 200
     :body   (pr-str q-result)}))

到运行服务器我在REPL中执行这个函数。

(defn run-dev
  "The entry-point for 'lein run-dev'"
  [& args]
  (println "\nCreating your [DEV] server...")
  (-> service/service
      (merge {:env                     :dev
              ::server/join?           false
              ::server/routes          #(deref #'service/routes)
              ::server/allowed-origins {:creds true :allowed-origins (constantly true)}})
      server/default-interceptors
      server/dev-interceptors
      server/create-server
      server/start))

关于 Pedestal 的 CORS 似乎没有太多信息。我查看了 cors example,但它似乎可以正常工作,而我的却不行。是否有另一个拦截器需要添加到我的路由或我在这里缺少的某种配置设置?

My original response:

The purpose of CORS is to limit the origin of the requests. You have to purposely tell it where requests can come from. This will fix it.

(def service {;other config stuff
              io.pedestal.http/allowed-origins ["http://localhost:3000"]}

这似乎是重复的 question. Apparently javascript ajax requests are by definition limited to single origin. That code would work in production only if the GET request is made by clj-http or http-kit on the ring server that spawn http://localhost:3000 然后一个 cljs-http ajax 请求被发送到端口 3000 上的同一个环形服务器。我仍然不知道为什么你的 运行-dev 不起作用,但如果你用 运行 调用 lein,这绝对是正在发生的事情。

我找到问题了。事实证明,一个错误被抛出,但是,它被我的调试器吞没并隐藏了。只需在我的处理程序函数周围添加一个 try catch 即可解决问题。

(defn db-query
  [req]
  (try
    (let [edn-params (:edn-params req)
          q (:query edn-params)
          args (:args edn-params)
          q-result (apply d/q q (d/db conn) args)]
      {:status 200
       :body   (pr-str q-result)})
    (catch Exception ex
      {:status 400
       :body   "Not authorized"})))