-
Notifications
You must be signed in to change notification settings - Fork 88
Description
Unexpected 404 Error when serving Kobweb 404 Page on Ktor Server.
- Kobweb libs version:
0.20.4 - Ktor version:
3.1.1
Description
I'm trying to get the Ktor server working with the Kobweb static site.
This issue should have low priority as the workaround works as expected.
The Kobweb 404 page:
// pages/404.kt
@Page
@Composable
fun NotFoundPage() {
PageLayout("Page not found") {
Text("This page is not found or it might have been moved somewhere else.")
}
}Configured the Ktor server to respond with the file content of this page:
install(StatusPages) {
status(HttpStatusCode.NotFound) { call, status ->
val message = LocalFileContent(File("./kobweb_site/404.html"))
call.respond(status, message)
}
}Which will respond successfully with this page if the JS file is not loaded, however, while executing the JS file, it causes a 404 while attempting to send an HTTP request in this line: https://github.com/varabyte/kobweb/blob/main/frontend/kobweb-core/src/jsMain/kotlin/com/varabyte/kobweb/navigation/Router.kt#L409
Reproduce steps
Consider downloading the minimal sample to save time. Run ./gradlew run and navigate to any page that doesn't exist.
OR:
- Create a new Kobweb project with a 404 page in
pagesand export the Kobweb as static layoutkobweb export --layout static -p site. - Create a new Ktor server project with
StatusPagesand Routing` plugins. - Move the
site/.kobweb/siteto the current working directory of the Ktor server root project with the directory namekobweb_site. - Setup the Ktor server to respond with the
404.htmlfile in case of 404 status:
fun Application.module() {
val kobwebSiteDirectory = Path("kobweb_site")
routing {
staticFiles("/", kobwebSiteDirectory.toFile()) {
extensions("html")
}
}
install(StatusPages) {
status(HttpStatusCode.NotFound) { call, _ ->
// This is identical to call.respondFile() but with 404 status.
val message = LocalFileContent(kobwebSiteDirectory.resolve("404.html").toFile())
call.respond(HttpStatusCode.NotFound, message)
}
}
}- Navigate to any route that doesn't exist.
- The
404.htmlpage is displayed correctly for a very short time but as the JS code executes, you will get404as the site router trying to navigate to a new route. This is the related line: https://github.com/varabyte/kobweb/blob/main/frontend/kobweb-core/src/jsMain/kotlin/com/varabyte/kobweb/navigation/Router.kt#L409).
You could also try to rename the JS file so the 404.html can't load it: mv temp.js invalid_temp.js. Now navigate to any route that doesn't exist and the page is displayed correctly but site functionality is broken. This confirms the issue is related to the JS code.
Workaround
A workaround is to redirect to 404:
status(HttpStatusCode.NotFound) { call, _ ->
// Using 404.html instead of 404 also works as expected if the extensions are configured correctly.
call.respondRedirect("/404")
}Important
For this workaround to work correctly, the staticFiles block must be configured to use extensions with html instead of setting the default to index.html
staticFiles("/", kobwebSiteDirectory.toFile()) {
- default("index.html")
+ extensions("html")
}Using default("index.html") instead of extensions("html") will load the HTML version of the page without the JS script loaded causing site functionality to be broken.
Warning
Using both default("index.html") and extensions("html") will cause the server to always return index.html in case the page is not found which is not expected, so the default should not be set.
According to my testing, adding html to extensions should be always used instead of setting the default to index.html, at least when hosting a Kobweb static site.