15

This should be an easy one, but it's not been so far. I've been working with vert.x 2 for a bit and switched to vert.x 3 recently. I thought I'd try a simple vertx-web example but can't get past a simple serving up of static files.

My server class contains the following snippets:

    HttpServer server = vertx.createHttpServer();
    Router router = ...;
    router.route("/static/*").handler(StaticHandler.create().setCachingEnabled(false));
    server.requestHandler(router::accept).listen(ctx.port);

I'm using Eclipse, but have also been trying running vertx from the the command line. I'm also using Maven. I have three webroot folders, and vert.x can find none of them:

myproject/webroot
myproject/src/main/resources/webroot
myproject/src/main/java/webroot

Each of those 'webroot's contains an index.html, and a css/base.css file.

The first one is in my project's root folder. The second is in the Maven resources folder, and the third should be flat-out on my classpath. In my Eclipse run config, I added myproject/src/main/resources/webroot to the classpath, and I made sure my working directory was set to 'myproject'. When running from the command line, I'm in the myproject directory, and my script looks like this:

JAVA_OPTS="-Dmyproject.port=8099" CLASSPATH="src/main/java:src/main/resources:target/dependencies/*:target/classes" vertx run com.my.MyProject

No matter what, I always get 404s when I try any of these URLs:

http://localhost:8099
http://localhost:8099/
http://localhost:8099/index.html
http://localhost:8099/static/css/base.css

Anything else I need to be doing?

Mike Barlotta
  • 715
  • 4
  • 16
Dave Taubler
  • 1,081
  • 3
  • 12
  • 25

8 Answers8

7

The solution I found depends on the answer to the questions: where is the static content going to be at runtime, and from where would you like vertx to serve it?

In my case, the installed file system would be where the static content was located (not in a jar file), and I wanted vertx to serve it from that location so that it could be updated live. So, I disabled classpath resolving in the StaticHandler by setting the JVM system property vertx.disableFileCPResolving to true at vertx startup.

Then I placed the webroot folder under the directory from which the jvm is started. In my case, I'm using scripts that guarantee the jvm's cwd is always <app-root>/bin, so dropping the content in <app-root>/bin/webroot was sufficient. If you can't make guarantees about where the jvm will be started from, it might be tougher, because you may need to pass an absolute path to StaticHandler.webroot() pointing to this fixed location, but I think there is an open issue regarding support for this (see here).

If the static content is going to be packaged into a jar, it's a little simpler. You can add 'webroot' as a resource in the jar and place all the content of interest in there. In this case you don't want to disable classpath resolving, so either set vertx.disableFileCPResolving to false, or don't set it at all. Now when you run vertx, it will find webroot in the jar file and extract its contents to <cwd>/.vertx/.file-cache-<guid> (where cwd is wherever you started the jvm from), and serve the contents from there. Note that this isn't viable if you intend to be able to do live updates to the content, because any changes to the files under that directory will get lost when vertx shuts down, because vertx-web will delete that directory. On restart, it will retrieve the original files from the jar resource again, and changes will be lost.

Anyway, hope this helps.

Hoobajoob
  • 2,748
  • 3
  • 28
  • 33
6

Execute the following code at any breakpoint and it'll tell you the root directory from which it will resolve your resource request:

new File("").getCanonicalPath()

Request: localhost:8080/static/script.js

Handler:

router.route("/static/*").handler(StaticHandler.create("webroot"));

The file should be in MODULE_ROOT/webroot/script.js

Debug all the way into the StaticHandlerImpl#sendStatic method to see how your files are being resolved, and use the debug expression window liberally to interrogate the file system.

geg
  • 4,399
  • 4
  • 34
  • 35
5

The default classpath setting worked for me. I used the following hierarchy:

Keep the static file in main/resources/webroot directory

<AppRoot>/src/main/resources/webroot/static/index.html

And initialize vertx as follows:

import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServer;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.StaticHandler;

Vertx vertx = Vertx.vertx();

Router router = Router.router(vertx);
router.route().handler(StaticHandler.create());

vertx.createHttpServer().requestHandler(router::accept).listen(8080);

Now you can access it from this URL: http://localhost:8080/static/

Refer vertx-web documentation for more info.

devsathish
  • 2,339
  • 2
  • 20
  • 16
4

Alright, I'll somewhat answer my own question. First, I should point out that I was keying off of the static-content parts of the vertx-web docs (http://vertx.io/docs/vertx-web/js/#_serving_static_resources):

Any requests to paths handled by the static handler will result in files being served from a directory on the file system or from the classpath. The default static file directory is webroot but this can be configured.

In the following example all requests to paths starting with /static/ will get served from the directory webroot:

var StaticHandler = require("vertx-web-js/static_handler");

router.route("/static/*").handler(StaticHandler.create().handle);

and

Any requests to the root path / will cause the index page to be served. By default the index page is index.html. This can be configured with setIndexPage.

It seemed to me that if I didn't explicitly define a handler for "/", then index.html would implicitly be served. And it also seemed that just creating a StaticHandler and adding it to the router would suffice for CSS/JS/IMG resources. I think my assumptions were incorrect.

So I added the following, which seem to be what was needed:

first, I told the StaticHandler explicitly to look for a "webroot" folder:

router.route("/static/*").handler(StaticHandler.create("webroot").setCachingEnabled(false));

then, I explicitly added a route to my router to handle requests to "/":

router.route("/").handler(ctx -> {
        Logger.log("Got an HTTP request to /");
        ctx.response().sendFile("webroot/index.html").end();
});
Dave Taubler
  • 1,081
  • 3
  • 12
  • 25
  • 1
    Using Java and I have a webroot folder in resources then used `router.route().handler(StaticHandler.create().setWebRoot("webroot"));` – eodgooch Oct 22 '15 at 21:07
3

this solution worked for me, to add more details here is the folder structure for me

src
    main
        java
            com
                -- java files with vertx
        resources
            webroot
                html
                js
Kishore Tulsiani
  • 1,106
  • 13
  • 29
1

Static files kept in /src/main/resources/assets/

ex: index.html

Router router = Router.router(vertx);
router.route("/files/*").handler(StaticHandler.create("assets"));
vertx.createHttpServer().requestHandler(router::accept).listen(8080);

Now you can access it from http://localhost:8080/files/index.html

If you look at router.route("/files/*").handler(StaticHandler.create("assets"));

When a request matches /files/ it calls the StaticHandler which specifies assets folder as the web-root

niro
  • 405
  • 4
  • 8
1

Directory

<AppRoot>/webroot/index.html

Vertx

router.route("/app/*").handler(StaticHandler.create("webroot").setCachingEnabled(false));

URL

http://127.0.0.1/app/index.html

Add the following Java VM options to enable hot reload

-Dvertx.disableFileCPResolving=true
Anders B
  • 3,343
  • 1
  • 26
  • 17
0

I believe people are getting tripped up by the examples in the documentation for serving static resources at http://vertx.io/docs/vertx-web/kotlin/#_serving_static_resources -- some of the answers even go so far as to change the route path, which is not what is desired!

I have raised https://github.com/vert-x3/issues/issues/265 with details.

Among others, OP tried:

http://localhost:8099/static/css/base.css

That should have worked, the rest of the paths were not valid, and src/main/resources/webroot is a good place for packaged-up static resources.

kva1966
  • 611
  • 6
  • 8