如果中间件顺序错误,Compojure 会在 Firefox 中触发 "File not found" 错误

Compojure triggers "File not found" error in Firefox if middlewares are in the wrong order

经过多年的 Web 开发并在一年前发现了 Clojure,我想将这两件事结合起来。

开始使用 Compojure 后,我尝试使用中间件实现身份验证,该中间件以 403 代码响应,告诉用户进行身份验证。

这是我的代码:

(defn authenticated? [req]
  (not (nil? (get-in req [:session :usr]))))

(defn helloworld [req]
  (html5
    [:head
      [:title "Hello"]]
    [:body
      [:p "lorem ipsum"]]))

(defn backend [req]
  (html5
    [:head
      [:title "Backend"]]
    [:body
      [:p "authenticated"]]))

(defroutes all-routes
  (GET "/" [] helloworld)
  (context "/backend" []
    (GET "/" [] backend)))

(defn wrap-auth [handler]
  (fn [req]
    (if (authenticated? req)
      (handler req)
      (-> (response "Nope")
        (status 403)))))

(def app
  (-> (handler/site all-routes)
    (wrap-auth)
    (wrap-defaults site-defaults)))

有趣的部分来了:如果我 运行 如上所示的代码,Firefox 会中断并显示错误消息 "File not found"。打开调试工具栏,我看到一个 403 响应,内容 "Tm9wZQ==" 是 base 64 从我的 auth 中间件函数解码 "Nope"。当我将 wrap-auth 放在 wrap-defaults 之后时,一切正常。

我想了解那里发生了什么。你能帮帮我吗?

真的很难说出幕后发生的事情。 wrap-defaults 中间件带来了很多东西,一次可能有 10 个或更多包装器。您最好检查一下 its source code 并准确选择您需要的内容。

我可能猜想,出于某种原因,Ring 服务器将您的响应视为一个文件,因此它将其编码为 base64。尝试 return 具有适当 headers 的普通地图,如下所示:

{:status 403
 :body "<h1>No access</h1>"
 :headers {"Content-Type" "text/html"}}