2016-06-19 3 views
5

Vert.x 웹 서버를 사용하여 React 앱을 정적 콘텐츠로 제공하고 있습니다. 이 주소가 / 경로에서 제공되고 React 앱 내에는 react-router을 사용하는 자체 라우팅이 있으며 이는 어떤 페이지를 표시할지 결정해야합니다. 이것은 내가 localhost:12001을 요청함으로써 시작하고 또한 정확하게 경로가 그 시점에서 변경 처리하는 경우 예상대로 작동자바 vert.x 웹 서버를 사용하여 단일 페이지 rect 앱 제공

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 -> { // This serves up the React app 
    event.response().sendFile("webroot/index.html").end(); 
}); 
server.requestHandler(router::accept).listen(12001); 

:

지금까지 나는 다음 있습니다. 그러나 내가 페이지 경로 중 하나가 react router에 의해 처리 된 페이지를 새로 고치려고하면 서버 로그에 오류가 발생합니다 (페이지가 올바르게로드됩니다).

누가 문제가 여기에 있으며 어떻게 수정해야하는지 압니까? 파일을 반환 할 때

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) 
+0

난 당신이 브라우저가 vert.x 백엔드에 존재하지 않는 경로를 가져 오기 위해 시도 새로 고칠 때 너무 경로를 변경 새 URL을 생성하는 반응이라고 생각합니다. 난 당신이 HTML 파일에 이러한 사용자 정의 경로를 매핑하는 몇 가지 규칙을 작성해야 할 것 같아요. 어쩌면 생성 된 경로를 게시하여 HTML 파일로 변환하는 데 도움을 줄 수 있습니다. –

+0

페이지를 새로 고침 할 때 Chrome 콘솔에서 어떤 일이 발생하는지 확인합니다. 거기에서 reqeust가 실패하고있는 것을보아야합니다. 그런 다음 실패한 요청의 그림을 첨부하십시오. – haschibaschi

+0

어떤 Vert.x 버전을 사용하고 있습니까? – Vadeg

답변

1

. 대신 나는 내가 원하는 방식으로 행동하는 내 자신의 handler을 작성하기로 마음 먹었고 원래의 질문에 오류가 나타나지 않았습니다.

import io.vertx.core.Handler; 
import io.vertx.core.http.HttpServerRequest; 
import io.vertx.ext.web.RoutingContext; 
import org.apache.logging.log4j.LogManager; 
import org.apache.logging.log4j.Logger; 

public class ReactAppHandler implements Handler<RoutingContext> { 

    private static final Logger LOGGER = LogManager.getLogger(ReactAppHandler.class); 

    private static final String WEB_ROOT_DIR = "webroot"; 
    private static final String INDEX_HTML = "/index.html"; 

    @Override 
    public void handle(RoutingContext event) { 

     HttpServerRequest request = event.request(); 
     String path = event.normalisedPath(); 

     LOGGER.info("Received a request for [" + path + "]."); 

     String requestedFilepath = path; 

     if ("/".equals(requestedFilepath)) { 
      LOGGER.info("Requested file is root path. Remapping to return the index page."); 
      requestedFilepath = INDEX_HTML; 
     } 

     final String fileToCheck = WEB_ROOT_DIR + requestedFilepath; 
     LOGGER.info("Checking if file exists at [" + fileToCheck + "]."); 

     event.vertx().fileSystem().exists(fileToCheck, fileExistsCheck -> { 

      String fileToSend = WEB_ROOT_DIR + INDEX_HTML; 

      if (fileExistsCheck.succeeded() && fileExistsCheck.result()) { 
       LOGGER.info("File exists at path."); 
       fileToSend = fileToCheck; 
      } else { 
       LOGGER.info("Could not find requested file, the index page will be returned instead."); 
      } 

      LOGGER.info("Returning file [" + fileToSend + "]."); 
      request.response().sendFile(fileToSend); 
     }); 
    } 
} 
+0

처리기에서 설명하는 동작은 사용자가 요청한 동작과 다릅니다. 당신이해야 할 일은 파일이 존재하고 그것이 index.html로 재 전달되지 않는지를 확인하는 간단한 핸들러입니다. 이렇게하면 캐시 지원 등을 포함한 정적 핸들러의 모든 기능을 사용할 수 있습니다. –

2

여기, 최종 메소드를 호출하지 않아야

router.route(HttpMethod.GET, "/*").handler(StaticHandler.create()).failureHandler(event -> { // This serves up the React app 
    event.response().sendFile("webroot/index.html").end(); 
}); 

이유를 파일을 전송하는 최적의 응답에 파일을 펌프 할 비동기 호출 때문이다 당신이 전화를 걸면 응답을 닫습니다. NOW!

파일이 매우 작아서 OS가 한 번에 바로 실행할 수 있으므로 (브라우저가 올바르게 수신함) OS가 이미 완료되었을 때 연결을 닫으려고합니다. 너를 위해서.

당신이해야하는 것입니다 :이 문제에 많은 다른 접근을 시도하고 아무데도 없어

router.route(HttpMethod.GET, "/*").handler(StaticHandler.create()).failureHandler(event -> { // This serves up the React app 
    event.response().sendFile("webroot/index.html"); 
}); 
+0

감사합니다. 나는 그것을 시험해 보았고, 예외 상황 중 하나를 해결하는 것처럼 보이지만, 여전히 'java.lang.IllegalStateException : Head already written'오류가 발생하는 것으로 보입니다. –