perwendel / spark

A simple expressive web framework for java. Spark has a kotlin DSL https://github.com/perwendel/spark-kotlin
Apache License 2.0
9.65k stars 1.56k forks source link

Support multiple calls to staticFileLocation #568

Open jylin opened 8 years ago

jylin commented 8 years ago

It seems you currently can't call staticFileLocation twice (I didn't look at the source code, but it looks like the second call is ignored?).

I'd like to be able to have a static assets folder, but also use webjars. However, something like this doesn't seem to work: staticFileLocation("/public"); staticFileLocation("/META-INF/resources");

It looks like I can't access the files in "/META-INF/resources", but if I comment out the first line, then those files are successfully loaded.

vacax commented 8 years ago

this issue is important.

pgrisafi commented 8 years ago

+1 New to Spark. As a webjars fan, this is important. A quick and dirty hack I made, using a custom route and a guava cache Disclaimer: It works for me, maybe not for you. It does not handle multiple nested folders, but it is easy to extend to do so.

private static final LoadingCache<String, String> WEBJARS_CACHE = CacheBuilder.newBuilder()
           .maximumSize(1000)
           .expireAfterWrite(365, TimeUnit.DAYS)
           .build(
               new CacheLoader<String, String>() {
                   @Override
                 public String load(String fullPath) throws IOException {
                     InputStream inputStream = Application.class.getClassLoader().getResourceAsStream(fullPath);
                    return IOUtils.toString(inputStream);
                 }
               });

public static void main(String[] args) {
    staticFiles.location("public");
    get("/hello", (req, res) -> "Hello World");

    get("/webjars/:library/:version/:file",  (req, res) -> {
        String library = req.params("library");
        String version = req.params("version");
        String file = req.params("file");
        if(file.endsWith(".js")){
            res.type("application/javascript");   
        }
        if(file.endsWith(".css")){
            res.type("text/css");   
        }
        String fullPath = "META-INF/resources/webjars/" + library + "/" + version +"/" + file;
        return WEBJARS_CACHE.get(fullPath);
    });
}

I can access files using links like

<script src="/webjars/angularjs/1.5.6/angular.min.js"></script>
<link rel="stylesheet" href="/webjars/angular-material/1.1.0-rc4/angular-material.min.css">
N0odlez commented 8 years ago

I'm looking to implement this for you but could you give me a bit more detail in what the goal is?

drxaos commented 8 years ago

I have multiple jars with resource folder and I had to do some reflection magic to search static resources in all jars. https://github.com/drxaos/coins/blob/master/coins-spark/src/main/java/com/github/drxaos/coins/spark/config/Http.java#L78

johnnybigoode-zz commented 5 years ago

I'm late to the party eh? @pgrisafi I think your case can be solved using staticFileLocation("/META-INF/resources"); That can give you access to all webjars in a single staticFileLocation.

@drxaos Wouldn't be easier to just copy the files to the appropriate folder? Maven has a resource plug in that solves this https://maven.apache.org/plugins/maven-resources-plugin/examples/include-exclude.html

@perwendel Could you shed some light on this? I personally don't think that any service should have more static resources, but I did notice that the StaticFilesConfiguration.java file has a private List<AbstractResourceHandler> staticResourceHandlers = null; on line 50. On method consumeWithFileResourceHandlers on line 85 we seem to iterate over all registered resourceHandlers.

Maybe I'm being naive, but it's not that hard to add this.

buckelieg commented 4 years ago

I would prefer to have an array of Strings as the arguments of staticFileLocation method where I can enlist all ROOT directories for static files.