Skip to content

Commit

Permalink
Add cacheable versioned skiko
Browse files Browse the repository at this point in the history
  • Loading branch information
ilgonmic committed Dec 20, 2024
1 parent 3b1f866 commit 3e3c8cc
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.compiler.server.controllers

import org.springframework.beans.factory.annotation.Value
import org.springframework.core.io.FileSystemResource
import org.springframework.core.io.Resource
import org.springframework.http.*
Expand All @@ -14,22 +15,48 @@ import java.util.concurrent.TimeUnit
class ResourceRestController {
@GetMapping("/skiko.mjs")
fun getSkikoMjs(): ResponseEntity<Resource> {
return cacheableResource("/com/compiler/server/skiko.mjs", MediaType("text", "javascript"))
return nonCacheableResource("/com/compiler/server/skiko.mjs", MediaType("text", "javascript"))
}

@GetMapping("/skiko.wasm")
fun getSkikoWasm(): ResponseEntity<Resource> {
return nonCacheableResource("/com/compiler/server/skiko.wasm", MediaType("application", "wasm"))
}

private fun nonCacheableResource(path: String, mediaType: MediaType): ResponseEntity<Resource> {
return resource(path, mediaType)
}

@Suppress("unused")
@GetMapping("/skiko-{version}.mjs")
fun getVersionedSkikoMjs(@Value("\${kotlin.version}") version: String): ResponseEntity<Resource> {
return cacheableResource("/com/compiler/server/skiko.mjs", MediaType("text", "javascript"))
}

@Suppress("unused")
@GetMapping("/skiko-{version}.wasm")
fun getVersionedSkikoWasm(@Value("\${kotlin.version}") version: String): ResponseEntity<Resource> {
return cacheableResource("/com/compiler/server/skiko.wasm", MediaType("application", "wasm"))
}

private fun cacheableResource(path: String, mediaType: MediaType): ResponseEntity<Resource> {
return resource(path, mediaType) {
cacheControl = CacheControl.maxAge(365, TimeUnit.DAYS).headerValue
}
}

private fun resource(
path: String,
mediaType: MediaType,
headers: HttpHeaders.() -> Unit = {},
): ResponseEntity<Resource> {
val resourcePath = javaClass.getResource(path)?.path
?: return ResponseEntity.internalServerError().build()

val resource = FileSystemResource(resourcePath)
val headers = HttpHeaders().apply {
contentType = mediaType
cacheControl = CacheControl.maxAge(365, TimeUnit.DAYS).headerValue
headers()
}

return ResponseEntity(resource, headers, HttpStatus.OK)
Expand Down
109 changes: 109 additions & 0 deletions src/test/kotlin/com/compiler/server/SkikoResourceTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.compiler.server

import com.compiler.server.base.BaseExecutorTest
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.HttpHeaders
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers
import java.util.concurrent.TimeUnit

@SpringBootTest
@AutoConfigureMockMvc
class SkikoResourceTest : BaseExecutorTest() {
@Autowired
private lateinit var mockMvc: MockMvc

@Value("\${kotlin.version}")
private lateinit var kotlinVersion: String

@Test
fun `test non caching for skiko mjs resource`() {
val resourceUrl = "/api/resource/skiko.mjs" // Ensure this matches your resource path

mockMvc
.perform(MockMvcRequestBuilders.get(resourceUrl))
.andExpect(MockMvcResultMatchers.status().isOk) // Ensures HTTP status 200
.andExpect(
MockMvcResultMatchers.header().doesNotExist(HttpHeaders.CACHE_CONTROL)
)
.andExpect(
MockMvcResultMatchers.header().string(
HttpHeaders.CONTENT_TYPE,
"text/javascript"
)
)
}

@Test
fun `test caching headers for skiko mjs resource`() {
val resourceUrl = "/api/resource/skiko-$kotlinVersion.mjs" // Ensure this matches your resource path
val expectedCacheControl = "max-age=${TimeUnit.DAYS.toSeconds(365)}"

mockMvc
.perform(MockMvcRequestBuilders.get(resourceUrl))
.andExpect(MockMvcResultMatchers.status().isOk) // Ensures HTTP status 200
.andExpect(
MockMvcResultMatchers.header().exists(HttpHeaders.CACHE_CONTROL)
)
.andExpect(
MockMvcResultMatchers.header().string(
HttpHeaders.CACHE_CONTROL,
expectedCacheControl
)
)
.andExpect(
MockMvcResultMatchers.header().string(
HttpHeaders.CONTENT_TYPE,
"text/javascript"
)
)
}

@Test
fun `test caching headers for skiko wasm resource`() {
val resourceUrl = "/api/resource/skiko-$kotlinVersion.wasm"
val expectedCacheControl = "max-age=${TimeUnit.DAYS.toSeconds(365)}"

mockMvc
.perform(MockMvcRequestBuilders.get(resourceUrl))
.andExpect(MockMvcResultMatchers.status().isOk) // HTTP 200 status
.andExpect(
MockMvcResultMatchers.header().exists(HttpHeaders.CACHE_CONTROL)
)
.andExpect(
MockMvcResultMatchers.header().string(
HttpHeaders.CACHE_CONTROL,
expectedCacheControl
)
)
.andExpect(
MockMvcResultMatchers.header().string(
HttpHeaders.CONTENT_TYPE,
"application/wasm"
)
)
}

@Test
fun `test non caching for skiko wasm resource`() {
val resourceUrl = "/api/resource/skiko.wasm"

mockMvc
.perform(MockMvcRequestBuilders.get(resourceUrl))
.andExpect(MockMvcResultMatchers.status().isOk) // HTTP 200 status
.andExpect(
MockMvcResultMatchers.header().doesNotExist(HttpHeaders.CACHE_CONTROL)
)
.andExpect(
MockMvcResultMatchers.header().string(
HttpHeaders.CONTENT_TYPE,
"application/wasm"
)
)
}
}

0 comments on commit 3e3c8cc

Please sign in to comment.