Hi,tl;dr I am serving a hiccup template with relative links (i.e. "lib/extjs...js") from my "/" route. It works if I visit myserver/contextRoot/ but not myserver/contextRoot - how can I force contextRoot to be contextRoot/ ?[longer version]I am having a world of joy :) getting my app to work properly when run by "lein run server" without a context root and when served from tomcat with a context root. I have solved most of the problem by using relative URLs, as expected. It all works beautifully if I visit /index.html (because everything is relative to the directory index.html is in).This is a single page ExtJS application without any friendly bookmarks so the URL is pretty redundant.The next step was to replace index.html with "/" so somebody can simply visit server/ or server/contextRoot. The problem is that relative links served by "/contextRoot" will be relative to "/", not "/contextRoot/". If "contextRoot" serves a HTML page which contains a link to "lib/myfile" then /contextRoot will actually serve "/lib/myfile" which doesn't exist - I want it to serve "/contextRoot/lib/myfile". As exected /contextRoot/ will resolve to "/contextRoot/lib/myfile" which works.Forcing people to visit index.html (with a redirect from "/") is perfectly acceptable, but before giving in I wanted to ask for help. So help :)Thanks in advance.Col--
You received this message because you are subscribed to the Google Groups "Compojure" group.
To view this discussion on the web visit https://groups.google.com/d/msg/compojure/-/e3AATzWr7hoJ.
To post to this group, send email to comp...@googlegroups.com.
To unsubscribe from this group, send email to compojure+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/compojure?hl=en.
I have the same problem.
With the following:
(routes
(context "/a" []
(GET "" [] "2")
(GET "/" [] "3")
(GET "/b" [] "4")
(GET "c" [] "5")
(GET "*" [] "5"))
(GET "/a" [] "1"))
both "/a" and "/a/" result in "3". For "/a", I was expecting "2" or "1".
I want to say something like (GET "/a" [] (redirect "/a/")), so that my browser uses the correct base for relative urls. But how?
Thanks,
- Phil
I have the same problem.
With the following:
(routes
(context "/a" []
(GET "" [] "2")
(GET "/" [] "3")
(GET "/b" [] "4")
(GET "c" [] "5")
(GET "*" [] "5"))
(GET "/a" [] "1"))
both "/a" and "/a/" result in "3". For "/a", I was expecting "2" or "1".
I want to say something like (GET "/a" [] (redirect "/a/")), so that my browser uses the correct base for relative urls. But how?
Thanks,
- Phil
On Wednesday, 16 January 2013 13:41:29 UTC, Colin Yates wrote:Hi,tl;dr I am serving a hiccup template with relative links (i.e. "lib/extjs...js") from my "/" route. It works if I visit myserver/contextRoot/ but not myserver/contextRoot - how can I force contextRoot to be contextRoot/ ?[longer version]I am having a world of joy :) getting my app to work properly when run by "lein run server" without a context root and when served from tomcat with a context root. I have solved most of the problem by using relative URLs, as expected. It all works beautifully if I visit /index.html (because everything is relative to the directory index.html is in).This is a single page ExtJS application without any friendly bookmarks so the URL is pretty redundant.The next step was to replace index.html with "/" so somebody can simply visit server/ or server/contextRoot. The problem is that relative links served by "/contextRoot" will be relative to "/", not "/contextRoot/". If "contextRoot" serves a HTML page which contains a link to "lib/myfile" then /contextRoot will actually serve "/lib/myfile" which doesn't exist - I want it to serve "/contextRoot/lib/myfile". As exected /contextRoot/ will resolve to "/contextRoot/lib/myfile" which works.Forcing people to visit index.html (with a redirect from "/") is perfectly acceptable, but before giving in I wanted to ask for help. So help :)Thanks in advance.Col
--
You received this message because you are subscribed to the Google Groups "Compojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to compojure+...@googlegroups.com.
To post to this group, send email to comp...@googlegroups.com.
Visit this group at http://groups.google.com/group/compojure?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
IMHO, the Compojure context macro does not handle trailing slashes in
paths in a useful manner. It clashes with Clout routes which I
understand have to start with a leading "/" (where's the spec for
routes?).
I ended up following Sean's advice, and always using root relative
URLs. It turned out that there's some subtlety to how hiccup handles
contexts:
=> (with-base-url "x" (to-str (to-uri "a")))
"a"
=> (with-base-url "x" (to-str (to-uri "/a")))
"x/a"
So I can get hiccup to generate root relative URLs by using
(wrap-base-url), and ensuring each URL starts with a leading '/'.
On 12 April 2013 10:56, Philip Aston <phi...@mail.com> wrote:
IMHO, the Compojure context macro does not handle trailing slashes in
paths in a useful manner. It clashes with Clout routes which I
understand have to start with a leading "/" (where's the spec for
routes?).
Clout doesn't have any opinion on whether routes start with a "/" or not.
However, the point you make about the context macro is a good one. Currently it returns a 200 OK response for "/foo" and "/foo/" when it should be returning either a redirect or nil for one of them.
I ended up following Sean's advice, and always using root relative
URLs. It turned out that there's some subtlety to how hiccup handles
contexts:
=> (with-base-url "x" (to-str (to-uri "a")))
"a"
=> (with-base-url "x" (to-str (to-uri "/a")))
"x/a"
So I can get hiccup to generate root relative URLs by using
(wrap-base-url), and ensuring each URL starts with a leading '/'.
Well, sure. How else could it possibly work?
If you want a URI relative to the root, it needs to begin with a "/". This isn't anything Compojure or Ring specific.
OK. I was basing this on simple experimentation, and assuming it was down to Clout. Compojure routes defined without a leading "/" (whether within a context or not) did not seem to match anything useful.
Given my experience with other frameworks, I'd expect "/foo" to redirect to "/foo/". However, I'd prefer it if "/foo" returned nil, then the user can chose what to do using a separate route, or generalise it with middleware. Either way, I think context would also need implicitly to strip leading slashes from the wrapped routes.However, the point you make about the context macro is a good one. Currently it returns a 200 OK response for "/foo" and "/foo/" when it should be returning either a redirect or nil for one of them.
A couple of alternatives that Hiccup could have chosen:
- Map both "a" and "/a" to "x/a".
- Map "a" to "x/a" and leave "/a" unchanged. Arguably more useful, because the application could then use root relative URIs to some other module, outside the base URL.
Ideally we want the redirects to be consistent, so it would make more sense for "/foo/" to redirect to "/foo" rather than the other way around, since "/foo.html" looks a lot better than "/foo.html/".
On 13 April 2013 16:24, Philip Aston <phi...@mail.com> wrote:
OK. I was basing this on simple experimentation, and assuming it was down to Clout. Compojure routes defined without a leading "/" (whether within a context or not) did not seem to match anything useful.
Well, why would it? Without a context you're matching directly against the HTTP request URI, which in general has a leading "/".
Given my experience with other frameworks, I'd expect "/foo" to redirect to "/foo/". However, I'd prefer it if "/foo" returned nil, then the user can chose what to do using a separate route, or generalise it with middleware. Either way, I think context would also need implicitly to strip leading slashes from the wrapped routes.However, the point you make about the context macro is a good one. Currently it returns a 200 OK response for "/foo" and "/foo/" when it should be returning either a redirect or nil for one of them.
Ideally we want the redirects to be consistent, so it would make more sense for "/foo/" to redirect to "/foo" rather than the other way around, since "/foo.html" looks a lot better than "/foo.html/".
However, we also want to maintain nesting, so:
(context "/foo" [](GET "/" [] "one")(GET "/bar" [] "two"))
Should be the same as:
(routes(GET "/foo" [] "one")(GET "/foo/bar" [] "two"))
However, currently it produces the equivalent to:
(routes(GET "/foo" [] "one")(GET "/foo/" [] "one")(GET "/foo/bar" [] "two"))
That middle route ideally shouldn't be matched, although if you're using middleware that always removes the ending slash, that extra route is never reached, so in practise it's less of a big deal.
Some standard middleware for removing ending slashes might be useful, though...
A couple of alternatives that Hiccup could have chosen:
- Map both "a" and "/a" to "x/a".
- Map "a" to "x/a" and leave "/a" unchanged. Arguably more useful, because the application could then use root relative URIs to some other module, outside the base URL.
None of those alternatives would work in the way I think you'd expect.
Consider a page at, say, "/foo/bar" with two links, one leading to "a" and the other leading to "/a". Under normal circumstances, the links are resolved by the browser like so:
"a" => "/foo/a""/a" => "/a"
Now we introduce a base URL, "/x" using the wrap-base-url middleware. The current Hiccup behaviour means you get:
"a" => "/x/foo/a""/a" => "/x/a
Which you can see matches up to what we'd expect if you added a context. Both links now get a common prefix of "/x".
On the other hand, your first suggestion leads to:
"a" => "/foo/x/a""/a" => "/foo/x/a"
And your second suggestion:
"a" => "/foo/x/a""/a" => "/a"
Why would you ever say (context "/foo.html")?Ideally we want the redirects to be consistent, so it would make more sense for "/foo/" to redirect to "/foo" rather than the other way around, since "/foo.html" looks a lot better than "/foo.html/".
Or, you might specify:
(context "/foo/" [](GET "" [] "one")(GET "bar" [] "two"))
be the same as:
(routes(GET "/foo/" [] "one")(GET "/foo/bar" [] "two"))
Sorry, I wasn't clear, as I was working fromand omitted the leading "/" from "x/a". It would have been clearer if I'd said: Map both "a" and "/a" to "/x/a", giving
=> (with-base-url "x" (to-str (to-uri "/a")))
"x/a"
"a" => "/x/a""/a" => "/x/a"
On 14 April 2013 12:14, Philip Aston <phi...@mail.com> wrote:
Why would you ever say (context "/foo.html")?Ideally we want the redirects to be consistent, so it would make more sense for "/foo/" to redirect to "/foo" rather than the other way around, since "/foo.html" looks a lot better than "/foo.html/".
You wouldn't. The problem is more general than that.
If you have a route leading to "/foo/bar" and someone enters in "/foo/bar/", what should happen?
Returning a 404 for one and a 200 for the other isn't particularly user friendly, so one route needs to redirect to the other. Either "/foo/bar" redirects to "/foo/bar/", or conversely "/foo/bar/" redirects to "/foo/bar".
The simplest way to achieve this is to pick a rule and follow it consistently. For instance:
(defn wrap-remove-ending-slash [handler](fn [{uri :uri :as request}](if (.endsWith uri "/")(redirect (str/replace uri #"/$" ""))(handler request))))
In this case, if a route ends with a "/", we redirect to one without. You could also do it the other way around, but then "/foo.html" would redirect to "/foo.html/", which to my mind looks wrong.
Or, you might specify:
(context "/foo/" [](GET "" [] "one")(GET "bar" [] "two"))
be the same as:
(routes(GET "/foo/" [] "one")(GET "/foo/bar" [] "two"))
But then you lose the ability to nest without changing code.
Consider a set of routes:
(defroutes number-routes(GET "/" [] "one")(GET "/bar" [] "two"))
These routes will work straight up, but we can also nest them in a context without changing them:
(context "/foo" [] number-routes)
If we wrote the routes as "" and "bar" instead of "/" and "/bar", they wouldn't work at the top level.
Sorry, I wasn't clear, as I was working fromand omitted the leading "/" from "x/a". It would have been clearer if I'd said: Map both "a" and "/a" to "/x/a", giving
=> (with-base-url "x" (to-str (to-uri "/a")))
"x/a"
"a" => "/x/a""/a" => "/x/a"
Your system doesn't handle links relative to the current page correctly.