2016-11-09 2 views
1

Я пытаюсь настроить базовую HTTP и сервер WebSocket Vert.x, но маршрут WebSocket всегда возвращает 200 вместо 101.Vert.x WebSocket возвращение 200 вместо 101

public class PhilTheServer extends AbstractVerticle { 

    private final static int PORT = 8080; 

    @Override 
    public void start(Future<Void> fut) { 
     // Create a router object. 
     Router router = Router.router(vertx); 

     // We need cookies, sessions and request bodies 
     router.route().handler(CookieHandler.create()); 
     router.route().handler(BodyHandler.create()); 

     router.route().handler(SessionHandler.create(LocalSessionStore.create(vertx))); 

     // Simple auth service which uses a properties file for user/role info 
     AuthProvider authProvider = ShiroAuth.create(vertx, new ShiroAuthOptions() 
       .setType(ShiroAuthRealmType.PROPERTIES) 
       .setConfig(new JsonObject() 
        .put("properties_path", "src/main/resources/vertx-users.properties"))); 

     // We need a user session handler too to make sure the user is stored in the session between requests 
     router.route().handler(UserSessionHandler.create(authProvider)); 

     // Serve the static private pages from directory "webroot" 
     router.route("/static/*").handler(StaticHandler.create("webroot/static").setCachingEnabled(false)); 

     // Public Index Page 
     router.get("/").handler(ctx -> { 
      ctx.response().sendFile("webroot/index.html"); 
     }); 

     router.mountSubRouter("/api", APIRoutes.get(vertx, authProvider)); 

     // Default non-handled requests: 
     router.route().handler(ctx -> { 
      ctx.fail(404); 
     }); 

     // WEBSOCKET: 

     BridgeOptions opts = new BridgeOptions() 
      .addInboundPermitted(new PermittedOptions().setAddressRegex("*")) 
      .addOutboundPermitted(new PermittedOptions().setAddressRegex("*")); 

     // Create the event bus bridge and add it to the router. 
     SockJSHandler ebHandler = SockJSHandler.create(vertx).bridge(opts, event -> { 
      if (event.type() == BridgeEventType.SOCKET_CREATED) { 
       System.out.println("A socket was created"); 
      } else { 
       System.out.println(event.type()); 
      } 

      event.complete(true); 
     }); 

     router.route("/eventbus/*").handler(ebHandler); 

     // Create the HTTP server and pass the "accept" method to the request handler. 
     vertx 
      .createHttpServer() 
      .requestHandler(router::accept) 
      .listen(
        // Retrieve the port from the configuration, 
        // default to 8080. 
        config().getInteger("http.port", 8080), 
        result -> { 
         if (result.succeeded()) { 
          fut.complete(); 
         } else { 
          fut.fail(result.cause()); 
         } 
        } 
      ); 
    } 
} 

Вместо добавления SockJSHanlder я попытался использовать websocketHandler на HttpServer, и это работает нормально, но я хотел бы сделать это наоборот.

Мой код теста:

HttpClient httpClient = client.websocket(PORT, "localhost", "/eventbus", headers, ws -> { 
    ws.handler(buffer -> { 
     JsonObject message = new JsonObject(buffer.toString()); 

     assertTrue(message.containsKey("type")); 

     ws.close(); 

     async.complete(); 
    }); 

    ws.write(Buffer.buffer("{ \"type\": \"test\"}")); 
}); 

ответ

2

Вы должны переместить обработчик:

router.route("/eventbus/*").handler(ebHandler); 

выше в списке. Проблема в том, что у вас есть глобальные обработчики, которые будут выполняться первыми и не позволят этому обработчику обработать обновление протокола до sockjs. Эти обработчики являются:

router.route().handler(CookieHandler.create()); 
router.route().handler(BodyHandler.create()); 
router.route().handler(SessionHandler....); 
router.route().handler(ctx -> { 
    ctx.fail(404); 
}); 

Поскольку router.route() будет вызываться для любого пути они будут мешать вашему обновление протокола. Если вы переместите обработчик sockjs перед тем, что он должен быть выполнен первым, и ваш код должен работать.