noir-clojure / lib-noir

A set of libraries for ring apps, including stateful sessions.
Eclipse Public License 1.0
483 stars 47 forks source link

io/resource-path returns semi-URL as string #115

Open TGThorax opened 8 years ago

TGThorax commented 8 years ago

You might already know this, and this might even be intended behavior, but here I go: The noir.io/resource-path function returns a (semi-)URL path to the resource given, since clojure.java.io/resource returns a URL. This can become a problem when you don't know the implementation since characters can be encoded (like spaces -> %20) in the path. Therefore consider

  1. (if it is intended behavior) mentioning in the doc something about the URL origin so people can make a URI/URL out of it again before trying to get a file,
  2. (not intended) changing the implementation to for example (.. path toURI getPath) instead of just (.getPath path) since the URI.getPath() will decode and URL will not.

In particular the inconsistency is apparent using following code

(require '[clojure.java.io :as jio] '[noir.io :as io] '[clojure.string :as str])

(let [a (io/resource-path) ;;=> "/data/.../Pragmatic%20Clojure/.../public/"
      b (jio/resource "public/") ;;=> #object[java.net.URL 0x58c7bfe0 "/data/../Pragmatic%20Clojure/.../public/"]
      c (io/get-resource "")] ; the normal way, returns URL as well
  (map #(.exists (jio/file %)) [a (str/replace a "%20" " ") b c])
) ;;=> (false true true true)

It's important to note that the first one fails because the file can't be found due to the encoded chars.

Of course files should be retrieved using get-resource, so that's my reason for suspicion that it may be intended behavior.