This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-03-27
Channels
- # bangalore-clj (1)
- # beginners (27)
- # boot (16)
- # cider (14)
- # cljs-dev (94)
- # cljsrn (8)
- # clojure (229)
- # clojure-dev (5)
- # clojure-dusseldorf (6)
- # clojure-italy (8)
- # clojure-norway (8)
- # clojure-russia (22)
- # clojure-sanfrancisco (2)
- # clojure-spec (48)
- # clojure-uk (44)
- # clojurescript (47)
- # core-async (87)
- # cursive (43)
- # datascript (22)
- # datomic (20)
- # defnpodcast (5)
- # emacs (6)
- # hoplon (4)
- # jobs-rus (4)
- # keechma (2)
- # klipse (8)
- # leiningen (2)
- # luminus (2)
- # lumo (14)
- # om (38)
- # onyx (4)
- # overtone (3)
- # pedestal (41)
- # planck (72)
- # powderkeg (42)
- # proton (46)
- # protorepl (9)
- # reagent (9)
- # ring (47)
- # ring-swagger (5)
- # rum (7)
- # sql (22)
- # unrepl (1)
- # untangled (24)
- # vim (19)
- # yada (5)
Hello, I am wondering how to correctly serve static files in a uberwar. I have bunch of static files (html, css, etc) under resources/public
folder. I serve the login page with following route (GET "/" [] (resource-response "login.html"))
. This works fine because I defined public
folder as resource-path in project.clj
. However links between the files are broken (for example login page won't find its CSS file which is linked with href="styles/login-styles.css"
). So what is the best way how to overcome this? I also tried defining resources as :war-resource-paths
but then I cannot even serve the login page itself. Thanks for any advice đ
@petr.mensik are you using the wrap-resource
middleware?
Also you donât want to set resources/public
as a resources-path
Thereâs a reason we use a subdirectory.
@weavejester I am using compojure-api so I am not sure whether it's included in default middleware
let me take a look
so the subdir for frontend part of the application should be something like resources/public/my-app
?
ok, looks like it's not so I'll try adding it
ok, defining middleware as :middleware [wrap-session wrap-not-modified [wrap-resource "public"]]}
worked for me (EDIT - worked with lein ring server
, not in uberwar). However I am still wondering what is the best practice for static content serving? You mentioned that using resources/public
is wrong, can I ask what would be a better solution? thanks a lot
@petr.mensik Using resources/public
is correct; itâs adding resources/public
to the classpath thatâs wrong. You need some way of distinguishing between resources you want to make public, and resources you want to keep private.
https://github.com/ring-clojure/ring-defaults is a library that sets up sensible default middleware, and includes wrap-resource
.
To me it's still makes sense to put all the website related stuff (html, css, ...) into resources/public
and make it available to the classpath. Then I can have let's say resources/images
and these will be for internal use of my application and I am not going to make that public. So is anything wrong such a setup?
So it sounds to me I should have :war-resource-paths ["resources/public"]
and :resource-paths ["resources/images"]
With the only problem that this doesn't work when I package the application into the WAR file with lein ring uberwar
. Again, links between files are broken (and I guess this is because Tomcat is not prepending the application name before link)
Because
servers the login page without styles, however
works. So is there any standard way how to make application work for both development and deployment? Because I feel like I am trying to reinvent wheel right now đ
And I cannot be the first one who wants to have relative links working when serving static content đ
@petr.mensik No, you shouldnât do that. Letâs say you have a file resources/public/foo.html
. If you set your :resource-paths
to [âresourcesâ]
, which is the default, then youâll be able to access your HTML file at public/foo.html
.
We can then say âany resource that starts with public/
is accessibleâ
But if you set the :resource-paths
to [âresources/publicâ], then your HTML file will be accessible at foo.html
, and how do you know if that is public or not?
Also, ignore :war-resource-paths
. Those are for war resources, which are different to the normal resources. Theyâre not on the classpath. Typically we donât use them in Clojure, we just use normal Java resources.
Ok, that makes sense, thanks. However I am not sure how for instance login.html
can link styles.css
when the CSS file is burried inside the WAR file under WEB-INF/classes/public
It doesnât matter where it is in the jar, or where it is on the filesystem. What matters is where the classpath is.
So WEB-INF/classes
is part of the classpath.
Effectively the classpath is lots of different places for resources merged together
Java tries them in order until it finds a matching file
While youâre developing, src
, test
and resources
are all on your classpath.
So if you try to find the resource public/foo.html
, itâll look for a file src/public/foo.html
, âtest/public/foo.html` and resources/public/foo.html
.
sure, I got this one. However what I meant is that if one static file is referencing other (like the example above), then it breaks. At least in my case, I can correctly serve login.html
with (GET "/" [] (resource-response "login.html" {:root "public"}))
however login.html
doesn't see the main.css
specified as href="styles/main.css"
Do you have a resources/public/styles/main.css
file?
Also if youâre serving from a subpath, styles/main.css
might be problematic
1) yes
2) what do you mean?
Sorry for being noob here, I just have a feeling that I am missing something important so I'd rather ask than stay as dumb as I am now đ
With relative paths, the ending slash on a URL is significant
So for instance...
If your page is at /foo
, then a link to styles/main.css
will go to /styles/main.css
If your page is at /foo/
, then a link to styles/main.css
will go to /foo/styles/main.css
.
So if your war file is being loaded from a subpath, you might run into problems with relative paths.
Thatâs why Hiccup has the wrap-base-url
middleware, for instance
That's the thing, I am refactoring older application so I dont really want to modify whole frontend part.
Are you serving from a subpath?
And does the issue of not being able to find styles/main.css
only occur when youâve deployed via a war?
Is it possible to use compojure middleware to reject a request with a Bad Request status?
Just return a 400 status code if the request is bad.
ah, makes sense. I think I can make it work but Iâm struggling with spec now đ
My application isnât returning â()
when I expect it to. I think itâs because (isa? '() compojure.response/Renderable)
is false. Renderable
is extended to ISeq
, but (isa? '() clojure.lang.ISeq)
is also false. Is this by design? I can file a bug report if desired.