Ответить с помощью заголовков кеша для изображений в Ktor

Как правильно отправлять обратно заголовки кеша для статических изображений, обслуживаемых Ktor?

У меня следующая настройка Ktor:

In my 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/")
        }
    }
}

Однако изображения возвращаются без заголовков кеширования, есть идеи?

введите описание изображения здесь

Обновление:

Изменение 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


person Jan Vladimir Mostert    schedule 17.09.2019    source источник


Ответы (2)


Оказывается, стандартная проверка eqauls выполняется на *, а не на фактическом типе файла, поэтому использование match вместо этого устраняет эту проблему:

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
        }
    }
}
person Jan Vladimir Mostert    schedule 28.09.2019

Вы можете установить заголовки кеширования по типу контента, используя: https://ktor.io/servers/features/caching-headers.html

person Community    schedule 17.09.2019
comment
как то, что я делаю в коде в моем вопросе? ContentType.Image.Any -> CachingOptions(CacheControl.MaxAge(maxAgeSeconds = 30 * 24 * 60 * 60)) - person Jan Vladimir Mostert; 17.09.2019