Serving up a single page rect app using java vert.x web server
<p>I'm making use of a <code>Vert.x</code> web server to serve up a <code>React</code> app as static content. I want this to be served up from the path <code>/</code>, then within the <code>React</code> app it has its own routing using <code>react-router</code> which should decide which page to show.</p>

<p>So far I have the following:</p>

<pre><code>Vertx vertx = Vertx.vertx();
HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
router.route().handler(BodyHandler.create());
router.route(HttpMethod.POST, "/rest/foo").handler(new FooHandler());
router.route(HttpMethod.GET, "/*").handler(StaticHandler.create()).failureHandler(event -&gt; { // This serves up the React app
    event.response().sendFile("webroot/index.html").end();
});
server.requestHandler(router::accept).listen(12001);
</code></pre>

<p>This works as expected if I start by requesting <code>localhost:12001</code> and it also correctly handles the path changes from that point onwards. However if I try to refresh one of the pages which has a path handled by the <code>react router</code> then I get a bunch of error generated in the server logs (the page does load correctly though).</p>

<p>Does anybody know what the issue is here and how to fix it?</p>

<pre><code>SEVERE: Unexpected exception in route
java.lang.IllegalStateException: Response has already been written
    at io.vertx.core.http.impl.HttpServerResponseImpl.checkWritten(HttpServerResponseImpl.java:561)
    at io.vertx.core.http.impl.HttpServerResponseImpl.end0(HttpServerResponseImpl.java:389)
    at io.vertx.core.http.impl.HttpServerResponseImpl.end(HttpServerResponseImpl.java:328)
    at co.uk.foo.webserver.server.WebServer.lambda$initialiseRoutes$0(WebServer.java:67)
    at co.uk.foo.webserver.server.WebServer$$Lambda$4/1197365356.handle(Unknown Source)
    at io.vertx.ext.web.impl.RouteImpl.handleFailure(RouteImpl.java:227)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:76)
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:94)
    at io.vertx.ext.web.impl.RoutingContextImpl.doFail(RoutingContextImpl.java:355)
    at io.vertx.ext.web.impl.RoutingContextImpl.fail(RoutingContextImpl.java:119)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl.lambda$sendStatic$2(StaticHandlerImpl.java:198)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl$$Lambda$17/1050258443.handle(Unknown Source)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl.wrapInTCCLSwitch(StaticHandlerImpl.java:245)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl.getFileProps(StaticHandlerImpl.java:264)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl.sendStatic(StaticHandlerImpl.java:184)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl.handle(StaticHandlerImpl.java:141)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl.handle(StaticHandlerImpl.java:51)
    at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:221)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:78)
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:94)
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl$BHandler.doEnd(BodyHandlerImpl.java:155)
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl$BHandler.end(BodyHandlerImpl.java:141)
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl.lambda$handle$34(BodyHandlerImpl.java:61)
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl$$Lambda$14/1403708668.handle(Unknown Source)
    at io.vertx.core.http.impl.HttpServerRequestImpl.handleEnd(HttpServerRequestImpl.java:411)
    at io.vertx.core.http.impl.ServerConnection.handleEnd(ServerConnection.java:286)
    at io.vertx.core.http.impl.ServerConnection.processMessage(ServerConnection.java:404)
    at io.vertx.core.http.impl.ServerConnection.handleMessage(ServerConnection.java:134)
    at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.doMessageReceived(HttpServerImpl.java:515)
    at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.doMessageReceived(HttpServerImpl.java:421)
    at io.vertx.core.http.impl.VertxHttpHandler.lambda$channelRead$20(VertxHttpHandler.java:80)
    at io.vertx.core.http.impl.VertxHttpHandler$$Lambda$16/1532360211.run(Unknown Source)
    at io.vertx.core.impl.ContextImpl.lambda$wrapTask$18(ContextImpl.java:333)
    at io.vertx.core.impl.ContextImpl$$Lambda$11/511598695.run(Unknown Source)
    at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:225)
    at io.vertx.core.http.impl.VertxHttpHandler.channelRead(VertxHttpHandler.java:80)
    at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:124)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:318)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:304)
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:276)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:263)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:318)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:304)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
    at java.lang.Thread.run(Thread.java:745)

Jun 26, 2016 4:22:08 PM io.vertx.ext.web.impl.RoutingContextImplBase
SEVERE: Unexpected exception in route
java.lang.IllegalStateException: Head already written
    at io.vertx.core.http.impl.HttpServerResponseImpl.doSendFile(HttpServerResponseImpl.java:434)
    at io.vertx.core.http.impl.HttpServerResponseImpl.sendFile(HttpServerResponseImpl.java:334)
    at io.vertx.core.http.impl.HttpServerResponseImpl.sendFile(HttpServerResponseImpl.java:52)
    at io.vertx.core.http.HttpServerResponse.sendFile(HttpServerResponse.java:275)
    at io.vertx.core.http.HttpServerResponse.sendFile(HttpServerResponse.java:262)
    at co.uk.foo.webserver.server.WebServer.lambda$initialiseRoutes$0(WebServer.java:67)
    at co.uk.foo.webserver.server.WebServer$$Lambda$4/1197365356.handle(Unknown Source)
    at io.vertx.ext.web.impl.RouteImpl.handleFailure(RouteImpl.java:227)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:76)
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:94)
    at io.vertx.ext.web.impl.RoutingContextImpl.doFail(RoutingContextImpl.java:355)
    at io.vertx.ext.web.impl.RoutingContextImpl.fail(RoutingContextImpl.java:119)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl.lambda$sendStatic$2(StaticHandlerImpl.java:189)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl$$Lambda$17/1050258443.handle(Unknown Source)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl.getFileProps(StaticHandlerImpl.java:284)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl.sendStatic(StaticHandlerImpl.java:184)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl.handle(StaticHandlerImpl.java:141)
    at io.vertx.ext.web.handler.impl.StaticHandlerImpl.handle(StaticHandlerImpl.java:51)
    at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:221)
    at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:78)
    at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:94)
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl$BHandler.doEnd(BodyHandlerImpl.java:155)
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl$BHandler.end(BodyHandlerImpl.java:141)
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl.lambda$handle$34(BodyHandlerImpl.java:61)
    at io.vertx.ext.web.handler.impl.BodyHandlerImpl$$Lambda$14/1403708668.handle(Unknown Source)
    at io.vertx.core.http.impl.HttpServerRequestImpl.handleEnd(HttpServerRequestImpl.java:411)
    at io.vertx.core.http.impl.ServerConnection.handleEnd(ServerConnection.java:286)
    at io.vertx.core.http.impl.ServerConnection.processMessage(ServerConnection.java:404)
    at io.vertx.core.http.impl.ServerConnection.handleMessage(ServerConnection.java:134)
    at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.doMessageReceived(HttpServerImpl.java:515)
    at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.doMessageReceived(HttpServerImpl.java:421)
    at io.vertx.core.http.impl.VertxHttpHandler.lambda$channelRead$20(VertxHttpHandler.java:80)
    at io.vertx.core.http.impl.VertxHttpHandler$$Lambda$16/1532360211.run(Unknown Source)
    at io.vertx.core.impl.ContextImpl.lambda$wrapTask$18(ContextImpl.java:333)
    at io.vertx.core.impl.ContextImpl$$Lambda$11/511598695.run(Unknown Source)
    at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:225)
    at io.vertx.core.http.impl.VertxHttpHandler.channelRead(VertxHttpHandler.java:80)
    at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:124)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:318)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:304)
    at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:276)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:263)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:318)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:304)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
    at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
    at java.lang.Thread.run(Thread.java:745)
</code></pre>