Sirve favicon.ico y otros files estáticos con VertX

Estoy intentando servir un favicon y algunas fonts.

object Lion : AbstractVerticle() { @JvmStatic @Throws(IOException::class) fun main(args: Array<String>) { val vertx = Vertx.vertx() val router = Router.router(vertx) router.route().handler(CorsHandler.create("*") .allowedMethod(HttpMethod.GET) .allowedMethod(HttpMethod.POST) .allowedMethod(HttpMethod.OPTIONS) .allowedHeader("X-PINGARUNER") .allowedHeader("Content-Type")) // some json GET / POST routes here router.route().handler(FaviconHandler.create()); router.route().handler(StaticHandler.create()) vertx.createHttpServer().requestHandler { router.accept(it) }.listen(9090) } 

FaviconHandler lanza una exception que causa un "Error interno del server" cuando voy a http://localhost:9090/favicon.ico Mi favicon se encuentra en src/main/resources/webroot/favicon.ico

 Oct 22, 2016 11:16:42 PM io.vertx.ext.web.impl.RoutingContextImplBase SEVERE: Unexpected exception in route java.lang.RuntimeException: java.lang.NullPointerException at io.vertx.ext.web.handler.impl.FaviconHandlerImpl.init(FaviconHandlerImpl.java:148) at io.vertx.ext.web.handler.impl.FaviconHandlerImpl.handle(FaviconHandlerImpl.java:155) at io.vertx.ext.web.handler.impl.FaviconHandlerImpl.handle(FaviconHandlerImpl.java:33) at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:215) 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.CorsHandlerImpl.handle(CorsHandlerImpl.java:121) at io.vertx.ext.web.handler.impl.CorsHandlerImpl.handle(CorsHandlerImpl.java:38) at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:215) 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.impl.RouterImpl.accept(RouterImpl.java:79) at Lion$main$8.handle(Lion.kt:90) at Lion$main$8.handle(Lion.kt:43) at io.vertx.core.http.impl.ServerConnection.handleRequest(ServerConnection.java:286) at io.vertx.core.http.impl.ServerConnection.processMessage(ServerConnection.java:412) at io.vertx.core.http.impl.ServerConnection.handleMessage(ServerConnection.java:139) at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.lambda$createConnAndHandle$1(HttpServerImpl.java:712) at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:314) at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:190) at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.createConnAndHandle(HttpServerImpl.java:706) at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.doMessageReceived(HttpServerImpl.java:570) at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.doMessageReceived(HttpServerImpl.java:522) at io.vertx.core.http.impl.VertxHttpHandler.channelRead(VertxHttpHandler.java:76) at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:122) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:372) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:358) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:350) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:372) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:358) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:350) at io.vertx.core.http.impl.HttpServerImpl$Http1xOrHttp2Handler.http1(HttpServerImpl.java:1019) at io.vertx.core.http.impl.HttpServerImpl$Http1xOrHttp2Handler.channelRead(HttpServerImpl.java:990) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:372) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:358) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:350) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1334) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:372) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:358) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:926) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:129) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:610) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:551) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:465) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:437) at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:873) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.NullPointerException at io.vertx.ext.web.handler.impl.FaviconHandlerImpl$Icon.<init>(FaviconHandlerImpl.java:61) at io.vertx.ext.web.handler.impl.FaviconHandlerImpl$Icon.<init>(FaviconHandlerImpl.java:40) at io.vertx.ext.web.handler.impl.FaviconHandlerImpl.init(FaviconHandlerImpl.java:143) ... 48 more 

La eliminación de FaviconHandler y los FaviconHandler normales html , js y css están funcionando bien, pero las fonts no se publican.

 Failed to decode downloaded font: http://localhost:9090/fonts/glyphicons-halflings-regular.woff /#/tcr:1 OTS parsing error: incorrect file size in WOFF header 

Cuando voy directamente a esa fuente-url, el browser está intentando download la fuente como un file normal.

Esto parece una solución potencial, pero estoy viendo algo que no es mi favicón, solo un cuadrado de 16×16 con líneas distorsionadas, las fonts aún intentan downloadse y todavía dan el error en la console del browser.

  router.route("/favicon.ico").handler { it.response().putHeader("Content-Type", "image/x-icon").sendFile("webroot/favicon.ico") } router.route("/fonts/glyphicons-halflings-regular.woff").handler { it.response().putHeader("Content-Type", "application/font-woff").sendFile("webroot/fonts/glyphicons-halflings-regular.woff") } 

Entonces, para resumir, ¿cómo hago para que StaticHandler sirva correctamente los files .woff y .ico con los MimeTypes correctos y que no descargue esos files?

Solución :

El primer problema que tuve fue que la sombra maven no estaba copyndo todos los files de fonts en el contenedor por alguna razón.

Copiar explícitamente los files de fonts en la compilation y deshabilitar el filtrado de resources para las fonts parece haber solucionado el problema de la fuente.

 <build> <sourceDirectory>${basedir}/src/main/java</sourceDirectory> <resources> <resource> <directory>${basedir}/src/main/resources</directory> <filtering>true</filtering> </resource> <resource> <directory>${basedir}/src/main/resources/fonts</directory> <filtering>false</filtering> </resource> </resources> 

Luego se arregló el service de las fonts del directory de resources en lugar del directory de fonts (VertX simplemente no se publicará desde el directory de fonts por algún motivo, aunque los files estén allí)

enter image description here

  router.route("/fonts/glyphicons-halflings-regular.woff2").handler { it.response().sendFile("glyphicons-halflings-regular.woff2") } router.route("/fonts/glyphicons-halflings-regular.woff").handler { it.response().sendFile("glyphicons-halflings-regular.woff") } router.route("/fonts/glyphicons-halflings-regular.ttf").handler { it.response().sendFile("glyphicons-halflings-regular.ttf") } router.route().handler(StaticHandler.create().setCachingEnabled(true)); 

Favicon probablemente se está almacenando en caching, aún está investigando, el favicon no es tan crítico para solucionar en este momento.

 router.route("/favicon.ico").handler(FaviconHandler.create("favicon.ico")) 

Favicon.ico:

Simplemente mueva su file favicon.ico hasta un nivel en la carpeta de resources directamente:

 /src/main/resources/favicon.ico 

Alternativamente, cambie su FaviconHandler para pasar la ruta y el nombre del file:

 router.route().handler(FaviconHandler.create(FaviconHandler.create("webroot/favicon.ico"))) 

Su código asume que FaviconHandler también respeta la webroot configurada en StaticHandler pero no lo hace. Eso es puramente una propiedad de StaticHandler y, por FaviconHandler tanto, FaviconHandler busca el recurso en los resources/ less que especifique una ruta relativa. Cuando ese recurso no se encuentra, usa el resultado de getResourceAsStream("favicon.ico") que es null y se bloquea.

Si miras la testing unitaria de FaviconHandlerImpl , verás que colocan el file favicon.ico en la raíz de los resources en lugar de webroot .


Archivos WOFF:

En cuanto a los files de fonts, está buscando en el lugar equivocado para el problema. No tiene nada que ver con los types MIME.

Lo más probable es que haya corrompido los files WOFF por crash. Esto podría haber sucedido cuando los cometiste con GIT y pensó que eran files de text y rompió los finales de línea corrompiéndolos. O usaste el plugin Maven Filter e hizo lo mismo, corrompiéndolos. O los cargó / descargó a través de FTP como files de text, el mismo problema.

Ver otras publicaciones sobre esto: https://stackoverflow.com/a/33792610/3679676

No especificas tu ruta de favicon, por lo que Vertx intenta localizar la ruta pnetworkingeterminada:

  if (path == null) { icon = new Icon(Utils.readResourceToBuffer("favicon.ico")); } 

Su favicon se encuentra en resources/webroot/favicon.ico , pero Vertx lo busca en resources/favicon.ico

Entonces puede especificar FaviconHandler.create("webroot/favicon.ico") o moverlo un directory hacia arriba.

En cuanto a los files WOFF, no pude reproducir el problema, ya que WOFF regresa con application/x-font-woff , lo que parece correcto.

  • Proxies de service Vert.x de Kotlin con vertx-codegen
  • Verticle (s) de Vert.x configuration JSON / YAML (preferible por entorno)
  • Cómo crear verticle de fábrica en VertX?
  • Vert.x. ¿Cómo crear una aplicación de JVM políglota real?
  • Respuesta fragmentada de Vert.x con los datos de la database usando BLOB e hibernación
  • Tengo una request de Vertx y necesito calcular una URL externa visible (pública)
  • Controlador de respuesta de coincidencia con request en VertX