diff --git a/server/server-app/src/main/kotlin/projektor/Application.kt b/server/server-app/src/main/kotlin/projektor/Application.kt index 338507241..d432d343b 100644 --- a/server/server-app/src/main/kotlin/projektor/Application.kt +++ b/server/server-app/src/main/kotlin/projektor/Application.kt @@ -7,10 +7,7 @@ import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule import io.ktor.application.Application import io.ktor.application.install import io.ktor.config.ApplicationConfig -import io.ktor.features.CORS -import io.ktor.features.CachingHeaders -import io.ktor.features.CallLogging -import io.ktor.features.ContentNegotiation +import io.ktor.features.* import io.ktor.http.CacheControl import io.ktor.http.ContentType import io.ktor.http.content.CachingOptions @@ -90,6 +87,11 @@ fun Application.main() { registry = metricRegistry } } + install(Compression) { + gzip { + matchContentType(ContentType.Application.Json, ContentType.Application.JavaScript) + } + } val authService: AuthService by inject() val testResultsService: TestResultsService by inject() diff --git a/server/server-app/src/main/kotlin/projektor/util/GzipUtil.kt b/server/server-app/src/main/kotlin/projektor/util/GzipUtil.kt new file mode 100644 index 000000000..5e13f7741 --- /dev/null +++ b/server/server-app/src/main/kotlin/projektor/util/GzipUtil.kt @@ -0,0 +1,4 @@ +import java.util.zip.GZIPInputStream + +fun ungzip(content: ByteArray): String = + GZIPInputStream(content.inputStream()).bufferedReader(Charsets.UTF_8).use { it.readText() } diff --git a/server/server-app/src/test/kotlin/projektor/testrun/GetTestRunCompressionApplicationTest.kt b/server/server-app/src/test/kotlin/projektor/testrun/GetTestRunCompressionApplicationTest.kt new file mode 100644 index 000000000..5f128ba51 --- /dev/null +++ b/server/server-app/src/test/kotlin/projektor/testrun/GetTestRunCompressionApplicationTest.kt @@ -0,0 +1,64 @@ +package projektor.testrun + +import io.ktor.http.HttpHeaders +import io.ktor.http.HttpMethod +import io.ktor.http.HttpStatusCode +import io.ktor.server.testing.handleRequest +import io.ktor.server.testing.withTestApplication +import io.ktor.util.KtorExperimentalAPI +import kotlin.test.assertNotNull +import org.junit.jupiter.api.Test +import projektor.ApplicationTestCase +import projektor.TestSuiteData +import projektor.incomingresults.randomPublicId +import projektor.server.api.TestRun +import strikt.api.expectThat +import strikt.assertions.hasSize +import strikt.assertions.isEqualTo +import ungzip + +@KtorExperimentalAPI +class GetTestRunCompressionApplicationTest : ApplicationTestCase() { + @Test + fun `when gzip accept header included should compress test run response`() { + val publicId = randomPublicId() + + withTestApplication(::createTestApplication) { + handleRequest(HttpMethod.Get, "/run/$publicId") { + testRunDBGenerator.createTestRun( + publicId, + listOf( + TestSuiteData("testSuite1", + listOf("testSuite1TestCase1", "testSuite1TestCase2"), + listOf(), + listOf() + ), + TestSuiteData("testSuite2", + listOf("testSuite2TestCase1", "testSuite2TestCase2", "testSuite2TestCase3"), + listOf(), + listOf() + ) + ) + ) + + addHeader(HttpHeaders.AcceptEncoding, "gzip") + }.apply { + expectThat(response.status()).isEqualTo(HttpStatusCode.OK) + + val responseBytes = response.byteContent + assertNotNull(responseBytes) + + val uncompressedResponse = ungzip(responseBytes) + + val responseRun = objectMapper.readValue(uncompressedResponse, TestRun::class.java) + assertNotNull(responseRun) + + expectThat(responseRun.id).isEqualTo(publicId.id) + + val testSuites = responseRun.testSuites + assertNotNull(testSuites) + expectThat(testSuites).hasSize(2) + } + } + } +} diff --git a/server/test/load-test/getRunLarge.js b/server/test/load-test/getRunLarge.js index 69aee40bb..291e5b1a9 100644 --- a/server/test/load-test/getRunLarge.js +++ b/server/test/load-test/getRunLarge.js @@ -43,6 +43,8 @@ export function setup() { return { testId: testId } } +const getParams = {headers: {"Accept-Encoding": "gzip"}}; + export default function (data) { const testId = data.testId; @@ -51,10 +53,10 @@ export default function (data) { } group('fetch test run details', () => { - const testRunResponse = http.get(`http://localhost:8080/run/${testId}`); + const testRunResponse = http.get(`http://localhost:8080/run/${testId}`, getParams); check(testRunResponse, statusCheck200); - const testRunSummaryResponse = http.get(`http://localhost:8080/run/${testId}/summary`); + const testRunSummaryResponse = http.get(`http://localhost:8080/run/${testId}/summary`, getParams); check(testRunSummaryResponse, statusCheck200); }) }; \ No newline at end of file