我发现了Ktor GraalVM https://ktor.io/docs/graalvm.html的例子,它运行得非常好。但是,如何服务静态资源,如图像或更重要的js (javascript)文件?
我有:
routing {
get("/") {
call.respondText("Hello GraalVM!")
call.application.environment.log.info("Call made to /")
}
static("/") {
resources("img")
}
}新代码是“静态”(“/”).再问一遍:是否有可能为静态内容服务?当然,我仍然希望有本机GraalVM输出(可执行文件)。
http://0.0.0.0:8080/工作和服务:“你好GraalVM!”输出。但是http://0.0.0.0:8080/img/test.png (在参考资料中-> img文件夹中有一个文件test.png)返回404 not。
发布于 2022-10-20 15:20:11
我让它成功了..。并找到了为什么它不能只使用经典代码:
static("/") {
staticBasePackage = "static"
static("img") {
resources("img")
}
}...but首先是调用的片段,即日志:
>>> url.protocol = resource答案是..。它通常作为一个文件工作,但是在本机GraalVM中这是作为一个资源来寻找的。原始代码:
@InternalAPI
public fun resourceClasspathResource(url: URL, path: String, mimeResolve: (String) -> ContentType): OutgoingContent? {
return when (url.protocol) {
"file" -> {
val file = File(url.path.decodeURLPart())
if (file.isFile) LocalFileContent(file, mimeResolve(file.extension)) else null
}
"jar" -> {
if (path.endsWith("/")) {
null
} else {
val zipFile = findContainingJarFile(url.toString())
val content = JarFileContent(zipFile, path, mimeResolve(url.path.extension()))
if (content.isFile) content else null
}
}
"jrt" -> {
URIFileContent(url, mimeResolve(url.path.extension()))
}
else -> null
}
}在这里,如您所见,这里不支持资源。我不得不像这样重写代码:
// "new version" of: io.ktor.server.http.content.StaticContentResolutionKt.resourceClasspathResource
fun resourceClasspathResourceVersion2(url: URL, path: String, mimeResolve: (String) -> ContentType, classLoader: ClassLoader): OutgoingContent? {
println(">>> url.protocol = ${url.protocol}")
return when (url.protocol) {
"file" -> {
val file = File(url.path.decodeURLPart())
println(">>> file = $file")
if (file.isFile) {
val localFileContent = LocalFileContent(file, mimeResolve(file.extension))
println(">>> localFileContent = $localFileContent")
localFileContent
} else null
}
// ... here are other things which are in original version
"resource" -> {
println(">>> in resource")
val resourceName = url.path.substring(1)
println(">>> resourceName = $resourceName")
val resourceAsStream = classLoader.getResourceAsStream(resourceName)
val cnt = ByteArrayContent(resourceAsStream.readAllBytes(), ContentType.parse("image/gif"), HttpStatusCode.OK)
cnt
}
else -> null
}
}路由类(Routing.kt)的所有代码如下所示:
package io.ktorgraal.plugins
import io.ktor.http.*
import io.ktor.http.content.*
import io.ktor.server.application.*
import io.ktor.server.http.content.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import java.io.File
import java.net.URL
fun Application.configureRouting() {
// I use println not some Logger to make it simple... in native also
// (there are different problems in native compilations with loggers)
// "new version" of: io.ktor.server.http.content.StaticContentResolutionKt.resourceClasspathResource
fun resourceClasspathResourceVersion2(url: URL, path: String, mimeResolve: (String) -> ContentType, classLoader: ClassLoader): OutgoingContent? {
println(">>> url.protocol = ${url.protocol}")
return when (url.protocol) {
"file" -> {
val file = File(url.path.decodeURLPart())
println(">>> file = $file")
if (file.isFile) {
val localFileContent = LocalFileContent(file, mimeResolve(file.extension))
println(">>> localFileContent = $localFileContent")
localFileContent
} else null
}
// ... here are other things which are in original version
"resource" -> {
println(">>> in resource")
val resourceName = url.path.substring(1)
println(">>> resourceName = $resourceName")
val resourceAsStream = classLoader.getResourceAsStream(resourceName)
val cnt = ByteArrayContent(resourceAsStream.readAllBytes(), ContentType.parse("image/gif"), HttpStatusCode.OK)
cnt
}
else -> null
}
}
// Starting point for a Ktor app:
routing {
get("/") {
call.respondText("Hello GraalVM!")
call.application.environment.log.info("Call made to /")
}
// not working... so we need below "reimplementation"
/*static("/") {
staticBasePackage = "static"
static("img") {
resources("img")
}
}*/
// "new version" of: io.ktor.server.http.content.StaticContentKt.resources
// ... because I need to call different function no resourceClasspathResource, but resourceClasspathResourceVersion2
get("/{pathParameterName...}") {
println(">>> this endpoint was called")
val relativePath = call.parameters.getAll("pathParameterName")?.joinToString(File.separator) ?: return@get
val mimeResolve: (String) -> ContentType = { ContentType.defaultForFileExtension(it) }
val classLoader: ClassLoader = application.environment.classLoader
val normalizedPath = relativePath // here I do not do normalization although in Ktor code such code exists
println(">>> normalizedPath = $normalizedPath")
val resources = classLoader.getResources(normalizedPath)
for (url in resources.asSequence()) {
println(">>> url = $url")
resourceClasspathResourceVersion2(url, normalizedPath, mimeResolve, classLoader)?.let { content ->
if (content != null) {
println(">>> about to return content")
call.respond(content)
}
}
}
}
}
}在这里,我也必须有一个“新版本”的io.ktor.server.http.content.StaticContentKt.resources,而不是改变整个库。然后,
http://localhost:8080/static/img/test/test.gif
调用工作并返回一个文件。
整个代码更改"https://github.com/ktorio/ktor-samples/tree/main/graalvm“是上面列出的Routing.kt类。您还应该将诸如gif这样的文件添加到资源中,->、静态->、img、->、测试、-> test.gif (嵌套只是为了显示结构)。
https://stackoverflow.com/questions/74055037
复制相似问题