Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vertx-web: where do I place webroot folder?

Tags:

java

vert.x

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?

like image 609
Dave Taubler Avatar asked Aug 03 '15 03:08

Dave Taubler


People also ask

What is handler in vertx?

This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. @FunctionalInterface public interface Handler<E> A generic event handler. This interface is used heavily throughout Vert.

What is Vertx Web?

Vert. x Web Client is an asynchronous HTTP and HTTP/2 client. The Web Client makes easy to do HTTP request/response interactions with a web server, and provides advanced features like: Json body encoding / decoding. request/response pumping.

What is routing context in Vertx?

public interface RoutingContext. Represents the context for the handling of a request in Vert. x-Web. A new instance is created for each HTTP request that is received in the Handler. handle(Object) of the router.


4 Answers

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.

like image 95
Hoobajoob Avatar answered Oct 17 '22 13:10

Hoobajoob


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.

like image 6
geg Avatar answered Oct 17 '22 13:10

geg


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.

like image 5
devsathish Avatar answered Oct 17 '22 12:10

devsathish


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();
});
like image 4
Dave Taubler Avatar answered Oct 17 '22 12:10

Dave Taubler