UrlCallback.kt
package com.hexagonkt.http.server.callbacks
import com.hexagonkt.core.ResourceNotFoundException
import com.hexagonkt.core.logging.Logger
import com.hexagonkt.core.media.mediaTypeOfOrNull
import com.hexagonkt.core.require
import com.hexagonkt.core.urlOf
import com.hexagonkt.http.model.ContentType
import com.hexagonkt.http.handlers.HttpContext
import java.net.URL
class UrlCallback(private val url: URL) : (HttpContext) -> HttpContext {
constructor(url: String) : this(urlOf(url))
private companion object {
val logger: Logger = Logger(UrlCallback::class)
}
override fun invoke(context: HttpContext): HttpContext {
val requestPath = when (context.pathParameters.size) {
0 -> ""
1 -> context.pathParameters.require("0")
else -> error("URL loading require a single path parameter or none")
}
check(!requestPath.contains("..")) { "Requested path cannot contain '..': $requestPath" }
logger.debug { "Resolving resource: $requestPath" }
return try {
if (requestPath.endsWith("/"))
throw ResourceNotFoundException("$requestPath not found (folder)")
val url = when {
requestPath.isEmpty() -> url.toString()
url.toString() == "classpath:/" -> "classpath:$requestPath"
else -> "$url/$requestPath"
}
val resource = urlOf(url)
val bytes = resource.readBytes()
val mediaType = mediaTypeOfOrNull(resource)
context.ok(bytes, contentType = mediaType?.let { ContentType(it) })
}
catch (e: ResourceNotFoundException) {
context.notFound(e.message ?: "")
}
}
}