Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set specific URL for static files using Spark Framework

I'm using Spark to serve a web page.. For the static files I initialize Spark like stated here:

So I have this structure:

/src/main/resources/public/
                      |-- foo/
                           |-- css/
                           |    |-- bootstrap.css
                           |-- js/
                           |    ...
                           |-- img/
                                ...

I made the foo folder to make a trick because my webpage is located under /foo url..like this:

http://www.example.com/foo/index

So my static files are loaded like this for example:

http://www.example.com/foo/css/bootstrap.css

What I want now is to have this path variable.. Because I have different environments and for example if I deploy this app in another domain I want it to be:

http://www.example2.com/superfoo/css/bootstrap.css

But for this I have to change the release and change the folder...

For the controllers I made this easily:

Example:

    Spark.get(this.appBasePath + "/users", (request, response) -> {
        return this.getUsersView(request);
    }, new FreeMarkerEngine());

this.appBasePath comes from a configuration that is loaded deciding the environment.

So what I am asking is to set programmatically the static files URL without making any folder. Is there any way to achieve this?

like image 651
Pablo Matias Gomez Avatar asked Jan 29 '15 20:01

Pablo Matias Gomez


1 Answers

I ended up working around this problem by generating a get route for all my static files. It is entirely possible that there are way easier ways of doing this directly in spark, but it took less time to write this code than to understand the details of the spark.resource package.

First, I define some helper functions to let me iterate over all files in a particular resource directory (requires Java 8):

/**
 * Find all resources within a particular resource directory
 * @param root base resource directory. Should omit the leading / (e.g. "" for all resources)
 * @param fn Function called for each resource with a Path corresponding to root and a relative path to the resource.
 * @throws URISyntaxException
 */
public static void findResources(String root,BiConsumer<Path,Path> fn) throws URISyntaxException {
    ClassLoader cl = Main.class.getClassLoader();
    URL url = cl.getResource(root);     
    assert "file".equals(url.getProtocol());
    logger.debug("Static files loaded from {}",root);
    Path p = Paths.get(url.toURI());
    findAllFiles(p, (path) -> fn.accept(p,p.relativize(path)) );
}
/**
 * Recursively search over a directory, running the specified function for every regular file.
 * @param root Root directory
 * @param fn Function that gets passed a Path for each regular file
 */
private static void findAllFiles(Path root, Consumer<Path> fn) {
    try( DirectoryStream<Path> directoryStream = Files.newDirectoryStream(root)) {
        for(Path path : directoryStream) {
            if(Files.isDirectory(path)) {
                findAllFiles(path, fn);
            } else {
                fn.accept(path);
            }
        }
    } catch (IOException ex) {}
}

Then I use this to define a new GET route for each file

String webroot = "/server1";
findResources("static", (root,path) -> {
    String route = webroot+"/"+path;
    String resourcePath = "/static/"+path.toString();
    logger.debug("Mapping {} to {}",route, resourcePath);
    get(webroot+"/"+path, (req,res) -> {
        Files.copy(root.resolve(path), res.raw().getOutputStream());
        AbstractFileResolvingResource resource = new ExternalResource(resourcePath);
        String contentType = MimeType.fromResource(resource);
        res.type(contentType );
        return "";
    } );
});
like image 136
Quantum7 Avatar answered Nov 09 '22 23:11

Quantum7