Kotlin 使用VertX提供favicon.ico和其他静态文件

Kotlin 使用VertX提供favicon.ico和其他静态文件,kotlin,vert.x,Kotlin,Vert.x,我正试着给你送一份便笺和一些字体 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

我正试着给你送一份便笺和一些字体

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
和普通
html
js
css
文件可以正常使用,但字体无法正常使用

Failed to decode downloaded font: http://localhost:9090/fonts/glyphicons-halflings-regular.woff
/#/tcr:1 OTS parsing error: incorrect file size in WOFF header
当我直接转到该字体url时,浏览器试图将该字体作为常规文件下载

这似乎是一个潜在的解决方案,但我看到的不是我的favicon,只是一个16x16的正方形,其中有扭曲的线条,字体仍在尝试下载,并且仍在浏览器控制台中给出错误

    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")
    }
总之,如何使
StaticHandler
使用正确的mimetype正确地提供
.woff
.ico
文件,而不让它下载这些文件

解决方案

我遇到的第一个问题是,出于某种原因,maven shade没有将所有字体文件复制到jar中

在构建时显式复制字体文件并禁用字体的资源筛选似乎已经解决了字体问题

<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>
Favicon可能正在缓存,仍在调查中,Favicon目前还没有那么关键

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

Favicon.ico:

只需将您的
favicon.ico
文件直接向上移动到
resources
文件夹中:

/src/main/resources/favicon.ico
或者,将您的
FaviconHandler
更改为传入路径和文件名:

router.route().handler(FaviconHandler.create(FaviconHandler.create("webroot/favicon.ico")))
您的代码假定
FaviconHandler
也尊重
StaticHandler
中设置的
webroot
,但它不尊重。这纯粹是
StaticHandler
的属性,因此
FaviconHandler
resources/
中查找资源,除非指定相对路径。当找不到该资源时,
null
将崩溃

如果查看
FaviconHandlerImpl
的单元测试,您将看到它而不是
webroot


WOFF文件:

至于你的字体文件,你在错误的地方寻找问题。它与MIME类型无关

更有可能的是,您在事故中损坏了WOFF文件。这可能发生在您使用GIT提交它们时,GIT认为它们是文本文件,因此它破坏了行尾,从而损坏了它们。或者你使用了Maven过滤器插件,它也做了同样的事情,腐蚀了他们。或者你通过FTP上传/下载了文本文件,同样的问题


请参阅关于此的其他帖子:

Favicon.ico:

只需将您的
favicon.ico
文件直接向上移动到
resources
文件夹中:

/src/main/resources/favicon.ico
或者,将您的
FaviconHandler
更改为传入路径和文件名:

router.route().handler(FaviconHandler.create(FaviconHandler.create("webroot/favicon.ico")))
您的代码假定
FaviconHandler
也尊重
StaticHandler
中设置的
webroot
,但它不尊重。这纯粹是
StaticHandler
的属性,因此
FaviconHandler
resources/
中查找资源,除非指定相对路径。当找不到该资源时,
null
将崩溃

如果查看
FaviconHandlerImpl
的单元测试,您将看到它而不是
webroot


WOFF文件:

至于你的字体文件,你在错误的地方寻找问题。它与MIME类型无关

更有可能的是,您在事故中损坏了WOFF文件。这可能发生在您使用GIT提交它们时,GIT认为它们是文本文件,因此它破坏了行尾,从而损坏了它们。或者你使用了Maven过滤器插件,它也做了同样的事情,腐蚀了他们。或者你通过FTP上传/下载了文本文件,同样的问题


请参阅其他关于此的帖子:

您没有指定favicon路径,因此Vertx尝试查找默认路径:

 if (path == null) {
    icon = new Icon(Utils.readResourceToBuffer("favicon.ico"));
 }
您的favicon位于
resources/webroot/favicon.ico
,但Vertex会在
resources/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
因此,您可以指定
FaviconHandler.create(“webroot/favicon.ico”)
或将其向上移动一个目录


关于WOFF文件,我无法重现该问题,因为WOFF返回了
应用程序/x-font-WOFF
,这似乎是正确的。

您没有指定favicon路径,因此Vertx尝试查找默认路径:

 if (path == null) {
    icon = new Icon(Utils.readResourceToBuffer("favicon.ico"));
 }
您的favicon位于
resources/webroot/favicon.ico
,但Vertex会在
resources/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
因此,您可以指定
FaviconHandler.create(“webroot/favicon.ico”)
或将其向上移动一个目录


关于WOFF文件,我无法重现该问题,因为WOFF返回了
应用程序/x-font-WOFF
,这似乎是正确的。

在我之后5分钟,您向我发布了相同的答案。对不起,Jayson,我花了时间发布了它。尽管如此,我认为没有理由生气,因为我还提供了一种不用移动任何地方就能为favicon服务的方法。你在我5分钟后就给我发了一个相同的答案。对不起,Jayson,我花了很多时间才发出来。尽管如此,我认为没有理由生气,因为我还提供了一种不用移动favicon的服务方式。Maven确实应该为此负责,首先Maven shade出于某种原因没有复制所有字体文件(只有一半),资源过滤也在腐蚀它,甚至在我得到它的复制之后,VertX仍然没有从字体目录中提供服务,因此将字体复制到资源中修复了它。在我的问题中看到我更新的解决方案。Maven确实应该为此负责,首先Maven shade出于某种原因没有复制所有字体文件(只有一半),资源过滤也会破坏它,即使在我复制它之后,VertX仍然没有从字体目录提供服务,所以将字体复制到资源中修复了它。在我的问题中查看我的更新解决方案。