Configure dropwizard to server index.html for (almost) all routes?
Asked Answered
T

3

9

I'm building a single page application which does all of it's html request routing on the client side and on the backend it uses dropwizard to provide a bunch of JSON services.

Essentially I'm having trouble getting the jetty in dropwizard to serve index.html for every request except to the following paths:

  /css
  /i18n
  /img
  /js
  /lib
  /services
  /templates

In fact I'm having a lot of trouble finding documentation that tells you how to setup any http routing at all. (I'm not a java guy).

Here's my simple yaml config:`

http:
  port: 8082
  adminPort: 8083
  rootPath: /service/*`

What do I need to add to acheive this.

Thanks

Teocalli answered 20/3, 2014 at 19:18 Comment(1)
how are you loading the react app from the index html coming from dropwizard?Narcotic
C
14

I've done this without changing my configuration. In fact, it only took me one line of code, to be put in the initialize method of my Application class:

bootstrap.addBundle(new AssetsBundle("/app", "/", "index.html", "static"));

Which basically says to serve anything under /app inside my JAR file under the URL pattern /, with index.html as the default file. This bundle will be named static, but you could pick whatever name you like.

Note that I'm using version 0.7.0-rc2 of Dropwizard, I'm not sure whether it works for earlier versions as well.

Cesium answered 25/3, 2014 at 9:23 Comment(3)
Alas we're only on 0.6.2 and this method isn't available, we're upgrade to .7 when it comes out though I'll give this a try then. Thanks for the reply.Teocalli
Did this change in 0.8.x? I'm trying to accomplish the same thing as OP where all requests to a path that doesn't point to a real asset gets served index.html. Adding an AssetsBundle as described here causes requests to "/" to get index.html, but a request to eg. "/foo/bar/bash" gets a 404.Acre
Having the same problem as @Acre in v0.9.1 :(Krystynakshatriya
A
4

@mthmulders answer worked for me when I went to "/" and would work on other url's while the page had not reloaded, but would not work when I refreshed the page at "/foo/bar/bash" or any other url. I fixed this issue by mapping any 404 response to return back the index.html page instead.

Add your static assets to your initialization method of your Application class:

bootstrap.addBundle(new AssetsBundle("/app", "/", "index.html", "static"));

Add the mapping to your new 404 page to your run method of your Application class:

ErrorPageErrorHandler eph = new ErrorPageErrorHandler();
eph.addErrorPage(404, "/error/404");
environment.getApplicationContext().setErrorHandler(eph);

Add your resource that maps to /error/404

@GET
@Path("/error/404")
@Produces(MediaType.TEXT_HTML)
public Response error404() {
        // get html file from resources here...
        return Response.status(Response.Status.OK)
                .entity("<html>foo</html>")
                .build();
}

After doing this I was able to refresh the page at "/foo/bar/bash" and it still returned back the index.html file.

Alfy answered 6/4, 2018 at 18:13 Comment(0)
A
-1

@jjbskir has the right answer. There are some other solutions here and here and here, but they introduce unnecessary dependencies.

Here is a more complete resource for serving the index page:

@Path("/errorpage")
public class ErrorService {

    private static String indexPage;

    @GET
    @Produces(MediaType.TEXT_HTML)
    public Response get404() {

        if (indexPage == null) {
            InputStream in = this.getClass().getResourceAsStream("/assets/index.html");
            try (Scanner scanner = new Scanner(in, StandardCharsets.UTF_8.name())) {
                indexPage = scanner.useDelimiter("\\A").next();
            }
        }

        return Response.status(Response.Status.OK)
                .entity(indexPage)
                .build();
    }

}

It caches the index page because it should never change at runtime. You might want to omit the caching if you use this service at development time.

Modify the call to the ErrorPageErrorHandler like this:

eph.addErrorPage(404, "/api/errorpage");

Don't forget the /api prefix if that's where your api is, and don't forget to register the resource.

Aorangi answered 19/3, 2021 at 17:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.