How to do HTTP 302 redirects with Noir Web framewo

2020-03-19 03:01发布

问题:

I'm helping to set up a Web site with Clojure's Noir framework, though I have a lot more experience with Django/Python. In Django, I'm used to URLs such as

http://site/some/url 

being 302-redirected automagically to

http://site/some/url/

Noir is more picky and does not do this.

What would be the proper way to do this automatically? Since good URLs are an important way of addressing into a site, and many users will forget the trailing slash, this is basic functionality I'd like to add to my site.

EDIT: Here is what finally worked for me, based on @IvanKoblik's suggestions:

(defn wrap-slash [handler]
  (fn [{:keys [uri] :as req}]
    (if (and (.endsWith uri "/") (not= uri "/"))
      (handler (assoc req :uri (.substring uri
                                0 (dec (count uri)))))
      (handler req))))

回答1:

I think this may be possible with a custom middleware. noir/server has public function add-middleware.

Here's a page from webnoir explaining how to do that.

Judging by the source code this custom middleware is executed first, so you'd be on your own in terms of sessions, cookies, url params, etc.


I wrote a very silly version of the middleware wrapper that checks if request URI ends with slash and if not redirects to URI with slash at the end:

(use [ring.util.response :only [redirect]])

(defn wrap-slash [handler]
  (fn [{:keys [uri] :as req}]
    (if (.endsWith uri "/")
      (handler req)
      (redirect
       (str uri "/")))))

I tested it on my ring/moustache web app and it worked reasonably well.


EDIT1 (Expanding my answer after your reply to my comment.)

You could use custom middleware to either add or strip URL of trailing slash. Just do something like this to strip away trailing slash:

(use [ring.util.response :only [redirect]])

(defn add-slash [handler]
  (fn [{:keys [uri] :as req}]
    (if (.endsWith uri "/")
      (handler (assoc req 
                      :uri (.substring uri 
                                       0 (dec (count uri)))))
      (handler req))))


回答2:

I found this useful:

(defpage "" []
  (response/redirect "/myapp/"))

/myapp -> /myapp/