0
votes

after doing web development for ages and discovering Clojure a year ago, I want to combine these two things.

After starting with Compojure, I try to implement authentication by using a middleware which responds with a 403 code, telling the user to authenticate.

This is my code:

(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)))

Here comes the funny part: If I run the code as shown above, Firefox breaks with the error message "File not found". Opening the debug toolbar, I see a 403 response and the content "Tm9wZQ==" which is base 64 decoded the "Nope" from my auth middleware function. When I put wrap-auth after wrap-defaults everything works fine.

I want to understand what's going on there. Can you help me?

1

1 Answers

1
votes

It's really difficult to say what's going on under the hood. The wrap-defaults middleware brings lots of stuff, maybe 10 or more wrappers at once. You'd better to examine its source code and choose exactly what you need.

I may guess that, for some reason, the Ring server considers your response being a file, so that's why it encodes it into base64. Try to return a plain map with proper headers as follows:

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