From 219a033d53f46096a3d27ea5e98aa08654670d11 Mon Sep 17 00:00:00 2001 From: Priveetee Date: Sun, 10 May 2026 19:20:03 +0200 Subject: [PATCH] fix: avoid compressing proxied images --- .../dev/typetype/server/CompressionConfig.kt | 20 +++++++++++ .../kotlin/dev/typetype/server/Plugins.kt | 13 +------ .../dev/typetype/server/ProxyRoutesTest.kt | 34 +++++++++++++++++++ 3 files changed, 55 insertions(+), 12 deletions(-) create mode 100644 src/main/kotlin/dev/typetype/server/CompressionConfig.kt diff --git a/src/main/kotlin/dev/typetype/server/CompressionConfig.kt b/src/main/kotlin/dev/typetype/server/CompressionConfig.kt new file mode 100644 index 0000000..b0fc892 --- /dev/null +++ b/src/main/kotlin/dev/typetype/server/CompressionConfig.kt @@ -0,0 +1,20 @@ +package dev.typetype.server + +import io.ktor.http.ContentType +import io.ktor.server.application.Application +import io.ktor.server.application.install +import io.ktor.server.plugins.compression.Compression +import io.ktor.server.plugins.compression.excludeContentType +import io.ktor.server.plugins.compression.gzip + +fun Application.configureCompression(): Unit { + install(Compression) { + gzip { + excludeContentType(ContentType.parse("application/vnd.apple.mpegurl")) + excludeContentType(ContentType.Image.Any) + excludeContentType(ContentType.Video.Any) + excludeContentType(ContentType.Audio.Any) + excludeContentType(ContentType.Application.OctetStream) + } + } +} diff --git a/src/main/kotlin/dev/typetype/server/Plugins.kt b/src/main/kotlin/dev/typetype/server/Plugins.kt index 7e00d50..2c97d3b 100644 --- a/src/main/kotlin/dev/typetype/server/Plugins.kt +++ b/src/main/kotlin/dev/typetype/server/Plugins.kt @@ -9,10 +9,6 @@ import io.ktor.serialization.kotlinx.json.json import io.ktor.server.application.Application import io.ktor.server.application.install import io.ktor.server.plugins.calllogging.CallLogging -import io.ktor.http.ContentType -import io.ktor.server.plugins.compression.Compression -import io.ktor.server.plugins.compression.excludeContentType -import io.ktor.server.plugins.compression.gzip import io.ktor.server.plugins.contentnegotiation.ContentNegotiation import io.ktor.server.plugins.cors.routing.CORS import io.ktor.server.plugins.ratelimit.RateLimit @@ -55,14 +51,7 @@ fun Application.configurePlugins(authService: AuthService) { install(ContentNegotiation) { json(Json { ignoreUnknownKeys = true; encodeDefaults = true }) } - install(Compression) { - gzip { - excludeContentType(ContentType.parse("application/vnd.apple.mpegurl")) - excludeContentType(ContentType.Video.Any) - excludeContentType(ContentType.Audio.Any) - excludeContentType(ContentType.Application.OctetStream) - } - } + configureCompression() val allowedOrigins = System.getenv("ALLOWED_ORIGINS") ?.split(",") ?.map { it.trim() } diff --git a/src/test/kotlin/dev/typetype/server/ProxyRoutesTest.kt b/src/test/kotlin/dev/typetype/server/ProxyRoutesTest.kt index 39b5abe..98d741b 100644 --- a/src/test/kotlin/dev/typetype/server/ProxyRoutesTest.kt +++ b/src/test/kotlin/dev/typetype/server/ProxyRoutesTest.kt @@ -55,6 +55,7 @@ class ProxyRoutesTest { install(Compression) { gzip { excludeContentType(ContentType.parse("application/vnd.apple.mpegurl")) + excludeContentType(ContentType.Image.Any) excludeContentType(ContentType.Video.Any) excludeContentType(ContentType.Audio.Any) excludeContentType(ContentType.Application.OctetStream) @@ -69,4 +70,37 @@ class ProxyRoutesTest { assertEquals(HttpStatusCode.PartialContent, response.status) assertNull(response.headers["Content-Encoding"]) } + + @Test + fun `GET proxy does not gzip image responses`() = testApplication { + coEvery { proxyService.pipe(any(), any()) } returns ExtractionResult.Success( + ProxyResponse( + status = 200, + contentType = "image/jpeg", + contentLength = 2048, + contentRange = null, + acceptRanges = null, + stream = ByteArrayInputStream(ByteArray(2048) { 1 }), + close = {}, + ) + ) + application { + install(ContentNegotiation) { json() } + install(Compression) { + gzip { + excludeContentType(ContentType.parse("application/vnd.apple.mpegurl")) + excludeContentType(ContentType.Image.Any) + excludeContentType(ContentType.Video.Any) + excludeContentType(ContentType.Audio.Any) + excludeContentType(ContentType.Application.OctetStream) + } + } + routing { proxyRoutes(proxyService) } + } + val response = client.get("/proxy?url=https://example.com/thumb.jpg") { + header("Accept-Encoding", "gzip") + } + assertEquals(HttpStatusCode.OK, response.status) + assertNull(response.headers["Content-Encoding"]) + } }