为 Ktor 中的图像响应缓存 headers

Respond with Cache headers for images in Ktor

为 Ktor 服务的静态图像发回缓存 headers 的正确方法是什么?

我有以下 Ktor 设置:

在我的 main:

embeddedServer(
        Netty,
        watchPaths = listOf("module"),
        module = Application::module,
        port = if (ENV.env == LOCAL) {
            8080
        } else {
            80
        }
    ).apply {
        start(wait = true)
    }

然后外主:

fun Application.module() {
    if (ENV.env != LOCAL) {
        install(ForwardedHeaderSupport)
        install(XForwardedHeaderSupport)
        install(HttpsRedirect)
    }
    install(CachingHeaders) {
        options { outgoingContent ->
            when (outgoingContent.contentType?.withoutParameters()) {
                ContentType.Image.Any -> CachingOptions(CacheControl.MaxAge(maxAgeSeconds = 30 * 24 * 60 * 60))
                else -> null
            }
        }
    }
    install(Compression) {
        gzip {
            priority = 1.0
        }
        deflate {
            priority = 10.0
            minimumSize(1024) // condition
        }
    }

    routing {
        static("/js/") {
            resources("/js/")
        }

        static("/css/") {
            resources("/css/")
        }

        static("/favicons") {
            resources("/favicons/")
        }

        static("/img/") {
            resources("/static/img/")
            resources("/static/images/")
            resources("/background/")
            resources("/logos/")
            resources("/icons/")
        }
    }
}

然而,图像返回时没有缓存 headers,有什么想法吗?

更新:

ContentType.Image.Any 更改为 ContentType.Image.JPEG 似乎可行。查看 Image 的源代码,它似乎映射到 ContentType(image, *) 但根本不匹配任何图像类型。

install(CachingHeaders) {
    options { outgoingContent ->
        when (outgoingContent.contentType?.withoutParameters()) {
            ContentType.Image.JPEG -> CachingOptions(
                cacheControl = CacheControl.MaxAge(
                    mustRevalidate = false,
                    maxAgeSeconds = 30 * 24 * 60 * 60,
                    visibility = CacheControl.Visibility.Public
                )
            )
            else -> null
        }
    }
}

同时提交了一个错误: https://github.com/ktorio/ktor/issues/1366

您可以按内容类型设置缓存 headers 使用:https://ktor.io/servers/features/caching-headers.html

事实证明,正在对 * 而不是实际文件类型进行标准 eqauls 检查,因此使用匹配来解决该问题:

install(CachingHeaders) {
    options { outgoingContent ->
        if (outgoingContent.contentType?.withoutParameters()?.match(ContentType.Image.Any) == true) {
            CachingOptions(
                cacheControl = CacheControl.MaxAge(
                    mustRevalidate = false,
                    maxAgeSeconds = 6 * 30 * 24 * 60 * 60,
                    visibility = CacheControl.Visibility.Public
                )
            )
        } else {
            null
        }
    }
}