Clojure 跨域错误 - 完全丢失
Posted
技术标签:
【中文标题】Clojure 跨域错误 - 完全丢失【英文标题】:Clojure Cross Origin Error - Totally Lost 【发布时间】:2020-01-21 15:47:21 【问题描述】:我在 Clojure 中有以下使用 Compojure 的简单服务器(这是一种环形模式)。一切都在开发中运行良好,现在我处于生产状态,我无法让 CORS 为我的一生工作 - 我有一个 wrap-preflight
函数,它似乎工作正常,但我在终端中不断收到 CORS 错误并且我的评论系统的帖子或获取请求都不起作用。我完全迷失了,非常沮丧,我四处打听,似乎没有人知道。
这是主要的core.clj
代码 - 如果有人有任何想法请告诉我。您可以在 thedailyblech.com 上实时查看错误(不是广告,但可能有助于调试)。
谢谢!
(ns clojure-play.core
(:use org.httpkit.server
[compojure.core :refer :all]
[compojure.route :as route]
[clojure.data.json :as json]
[clojure.tools.logging :only [info]]
[clojure-play.routes :as routes]
[ring.middleware.json :only [wrap-json-body]]
[ring.middleware.cors :refer [wrap-cors]])
(:require [monger.core :as mg]
[monger.collection :as mc]
[clojure.edn :as edn]
[clojure.java.io :as io]
[compojure.handler :as handler])
(:import [org.bson.types ObjectId]
[com.mongodb DB WriteConcern])
(:gen-class))
(println "in the beginning was the command line...")
(defonce channels (atom #))
(defn connect! [channel]
(info "channel open")
(swap! channels conj channel))
(defn notify-clients [msg]
(doseq [channel @channels]
(send! channel msg)))
(defn disconnect! [channel status]
(info "channel closed:" status)
(swap! channels #(remove #channel %)))
(defn ws-handler [request]
(with-channel request channel
(connect! channel)
(on-close channel (partial disconnect! channel))
(on-receive channel #(notify-clients %))))
(defn my-routes [db]
(routes
(GET "/foo" [] "Hello Foo")
(GET "/bar" [] "Hello Bar")
(GET "/json_example/:name" [] routes/json_example)
(GET "/json_example" [] routes/json_example)
(POST "/email" [] routes/post_email)
(POST "/write_comment" [] (fn [req] (routes/write_comment req db)))
(POST "/update_comment" [] (fn [req] (routes/update_comment req db)))
(GET "/read_comments/:path" [path] (fn [req] (routes/read_comments req db path)))
(GET "/read_comments/:path1/:path2" [path1 path2] (fn [req] (routes/read_comments req db (str path1 "/" path2))))
(GET "/ws" [] ws-handler)))
(defn connectDB []
(defonce connection
(let
[uri "mongodb://somemlabthingy"
:keys [conn db] (mg/connect-via-uri uri)]
:conn conn
:db db))
:db (:db connection)
:conn (:conn connection))
(def cors-headers
"Generic CORS headers"
"Access-Control-Allow-Origin" "*"
"Access-Control-Allow-Headers" "*"
"Access-Control-Allow-Methods" "GET POST OPTIONS DELETE PUT")
(defn preflight?
"Returns true if the request is a preflight request"
[request]
(= (request :request-method) :options))
(defn -main
"this is main"
[& args]
(println "hello there main")
(def db (get (connectDB) :db))
(println (read-string (slurp (io/resource "environment/config.edn"))))
(defn wrap-preflight [handler]
(fn [request]
(do
(println "inside wrap-preflight")
(println "value of request")
(println request)
(println "value of handler")
(println handler)
(if (preflight? request)
:status 200
:headers cors-headers
:body "preflight complete"
(handler request)))))
(run-server
(wrap-preflight
(wrap-cors
(wrap-json-body
(my-routes db)
:keywords? true :bigdecimals? true)
:access-control-allow-origin [#"http://www.thedailyblech.com"]
:access-control-allow-methods [:get :put :post :delete :options]
:access-control-allow-headers ["Origin" "X-Requested-With"
"Content-Type" "Accept"]))
:port 4000))
【问题讨论】:
应该将"Access-Control-Allow-Methods" "GET POST OPTIONS DELETE PUT"
改为"Access-Control-Allow-Methods" "GET, POST, OPTIONS, DELETE, PUT"
吗?
【参考方案1】:
CORS 中间件自动处理预检内容——您不需要单独的中间件,也不需要生成自己的标头等。
你让它包裹了routes
,这是正确的——所以首先进行CORS检查,然后是路由。您应该删除您的自定义预检中间件,它应该可以在那时工作。
我们在工作中使用wrap-cors
,我们遇到的唯一问题是允许足够的标头(一些由生产基础设施插入,例如负载平衡器)。我们最终得到了这个:
:access-control-allow-headers #"accept"
"accept-encoding"
"accept-language"
"authorization"
"content-type"
"origin"
对于它的价值,以下是我们所拥有的方法:
:access-control-allow-methods [:delete :get
:patch :post :put]
(你不需要:options
)
【讨论】:
谢谢伙计。原来是 nginx 问题。网络是一堆牙签,我告诉你。欣赏! 啊,可能类似于我们最初使用 CloudFront 时遇到的问题,以及它会/不会传递哪些标头。 @SeanCorfield,我在使用 system.components 时遇到了类似的问题,并且标题似乎不在响应中。你能帮忙吗? ***.com/questions/60536686/…【参考方案2】:研究了几个小时后,我发现this 对ring-cors github 上的issues post 非常有帮助,但文档严重缺乏。
使用链接的要点,我能够解决 CORS 问题:
; Copied from linked gist
(def cors-headers
"Generic CORS headers"
"Access-Control-Allow-Origin" "*"
"Access-Control-Allow-Headers" "*"
"Access-Control-Allow-Methods" "GET")
(defn preflight?
"Returns true if the request is a preflight request"
[request]
(= (request :request-method) :options))
(defn all-cors
"Allow requests from all origins - also check preflight"
[handler]
(fn [request]
(if (preflight? request)
:status 200
:headers cors-headers
:body "preflight complete"
(let [response (handler request)]
(update-in response [:headers]
merge cors-headers )))))
; my -main
(defn -main
"Main entry point"
[& args]
(let [port (Integer/parseInt (or (System/getenv "PORT") "8081"))]
(server/run-server
(all-cors
(wrap-defaults #'app-routes site-defaults))
:port port)
(println "Running on" port)))
这终于让我能够看到在 Chrome 开发工具中正确设置的标头,并且还摆脱了我的 React 前端的警告。
Access-Control-Allow-Headers: *
Access-Control-Allow-Methods: GET
Access-Control-Allow-Origin: *
【讨论】:
【参考方案3】:可能值得尝试并添加一个明确的
(OPTIONS "/*" req handle-preflight)
路由到您的 Compojure 路由 - 就我而言,这就是它起作用的原因。
【讨论】:
【参考方案4】:(RING-MIDDLEWARE-CORS/wrap-cors
:access-control-allow-credentials "true"
:access-control-allow-origin [#".*"]
:access-control-allow-headers #"接受" “接受编码” “接受语言” “授权” “内容类型” “起源”
:access-control-allow-methods [:get :put :post :delete :options])
【讨论】:
我是一名 clojure 和 clojurescript 开发人员。帮我解决这个问题。此设置正在使用中。 @Minal Chauhan 你为什么要-1?如果没有实际使用的例子,那是相当混乱的,所以我把它放上来。以上是关于Clojure 跨域错误 - 完全丢失的主要内容,如果未能解决你的问题,请参考以下文章