From e20de484b05ed26fb190d70ca3c7795de98d368a Mon Sep 17 00:00:00 2001 From: Lanius Trolling Date: Fri, 21 Jul 2023 13:49:59 -0400 Subject: [PATCH] Allow caching of factbook assets --- build.gradle.kts | 4 ++ src/main/kotlin/info/mechyrdia/Factbooks.kt | 26 +++++++++- .../kotlin/info/mechyrdia/lore/view_tpl.kt | 50 +++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 88c681e..0bf1ce0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -47,8 +47,10 @@ dependencies { implementation("io.ktor:ktor-server-core-jvm:2.3.2") implementation("io.ktor:ktor-server-netty-jvm:2.3.2") + implementation("io.ktor:ktor-server-caching-headers:2.3.2") implementation("io.ktor:ktor-server-call-id:2.3.2") implementation("io.ktor:ktor-server-call-logging:2.3.2") + implementation("io.ktor:ktor-server-conditional-headers:2.3.2") implementation("io.ktor:ktor-server-forwarded-header:2.3.2") implementation("io.ktor:ktor-server-html-builder:2.3.2") implementation("io.ktor:ktor-server-sessions-jvm:2.3.2") @@ -72,6 +74,8 @@ dependencies { implementation("org.slf4j:slf4j-api:2.0.7") implementation("ch.qos.logback:logback-classic:1.4.7") + implementation("io.ktor:ktor-server-conditional-headers-jvm:2.3.2") + implementation("io.ktor:ktor-server-caching-headers-jvm:2.3.2") } java { diff --git a/src/main/kotlin/info/mechyrdia/Factbooks.kt b/src/main/kotlin/info/mechyrdia/Factbooks.kt index 6203e33..cd73f1b 100644 --- a/src/main/kotlin/info/mechyrdia/Factbooks.kt +++ b/src/main/kotlin/info/mechyrdia/Factbooks.kt @@ -6,14 +6,17 @@ import info.mechyrdia.auth.* import info.mechyrdia.data.* import info.mechyrdia.lore.* import io.ktor.http.* +import io.ktor.http.content.* import io.ktor.server.application.* import io.ktor.server.engine.* import io.ktor.server.html.* import io.ktor.server.http.content.* import io.ktor.server.netty.* import io.ktor.server.plugins.* +import io.ktor.server.plugins.cachingheaders.* import io.ktor.server.plugins.callid.* import io.ktor.server.plugins.callloging.* +import io.ktor.server.plugins.conditionalheaders.* import io.ktor.server.plugins.forwardedheaders.* import io.ktor.server.plugins.statuspages.* import io.ktor.server.request.* @@ -45,6 +48,24 @@ fun Application.factbooks() { install(IgnoreTrailingSlash) install(XForwardedHeaders) + install(CachingHeaders) { + options { _, outgoingContent -> + if (outgoingContent is JarFileContent) + CachingOptions(CacheControl.MaxAge(maxAgeSeconds = 3600)) + else + null + } + } + + install(ConditionalHeaders) { + version { _, outgoingContent -> + if (outgoingContent is LocalFileContent) + listOf(LastModifiedVersion(outgoingContent.file.lastModified())) + else + emptyList() + } + } + install(CallId) { val counter = AtomicLong(0) generate { @@ -115,13 +136,16 @@ fun Application.factbooks() { staticResources("/static", "static", index = null) { preCompressed(CompressedFileType.BROTLI, CompressedFileType.GZIP) + enableAutoHeadResponse() } get("/lore/{path...}") { call.respondHtml(HttpStatusCode.OK, call.loreArticlePage()) } - staticFiles("/assets", File(Configuration.CurrentConfiguration.assetDir), index = null) + staticFiles("/assets", File(Configuration.CurrentConfiguration.assetDir), index = null) { + enableAutoHeadResponse() + } // Client settings diff --git a/src/main/kotlin/info/mechyrdia/lore/view_tpl.kt b/src/main/kotlin/info/mechyrdia/lore/view_tpl.kt index cecf7f3..c1e5809 100644 --- a/src/main/kotlin/info/mechyrdia/lore/view_tpl.kt +++ b/src/main/kotlin/info/mechyrdia/lore/view_tpl.kt @@ -6,6 +6,36 @@ import io.ktor.server.request.* import io.ktor.util.* import kotlinx.html.* +private val fonts = listOf( + "DejaVuSans-Bold.woff", + "DejaVuSans-BoldOblique.woff", + "DejaVuSans-Oblique.woff", + "DejaVuSans.woff", + "JetBrainsMono-ExtraBold.woff", + "JetBrainsMono-ExtraBoldItalic.woff", + "JetBrainsMono-Medium.woff", + "JetBrainsMono-MediumItalic.woff", + "NotoSans-Black.woff", + "NotoSans-BlackItalic.woff", + "NotoSans-Medium.woff", + "NotoSans-MediumItalic.woff", + "NotoSansGothic-Regular.woff", + "Oxanium-Bold.woff", + "Oxanium-ExtraBold.woff", + "Oxanium-Regular.woff", + "Oxanium-SemiBold.woff", + "thedish-language-alphabet.woff", + "tylan-language-alphabet-3.woff", +) + +private val images = listOf( + "external-link-dark.png", + "external-link.png", + "icon.png", + "panel-dark.png", + "panel.png", +) + fun ApplicationCall.page(pageTitle: String, navBar: List? = null, sidebar: Sidebar? = null, content: SECTIONS.() -> Unit): HTML.() -> Unit { val theme = request.cookies["FACTBOOK_THEME"] @@ -26,6 +56,26 @@ fun ApplicationCall.page(pageTitle: String, navBar: List? = null, sideb link(rel = "icon", type = "image/svg+xml", href = "/static/images/icon.png") + for (font in fonts) + link( + rel = "preload", + href = "/static/font/$font", + type = "font/woff" + ) { + attributes["as"] = "font" + attributes["crossorigin"] = "anonymous" + } + + for (image in images) + link( + rel = "preload", + href = "/static/images/$image", + type = "image/png" + ) { + attributes["as"] = "image" + attributes["crossorigin"] = "anonymous" + } + link(rel = "stylesheet", href = "/static/style.css") request.queryParameters["redirect"]?.let { redirect -> -- 2.25.1