How to serve static default content under each subfolder wIth ktor

387 Views Asked by At

I have a static route that works fine, but I would like to add a default document for any/all sub folders - default seems to only be able to take a fixed file to serve, with no way of asking it to look in the request directory.

The following will serve any static file under the "/export" directory when "/export/..." is requested, but if not found then the file "/index.html" is always returned instead of "export/.../index.html".

static("export") {
    files("export")
    default("index.html")
}

Is there any way to define this? It seems like a standard feature for a web server, so I may have just missed something obvious...

1

There are 1 best solutions below

1
On BEST ANSWER

default() handles only the top-level folder, for whatever reason. You can replace the files() and default() pair with a custom extension, looking like this:

fun Route.filesWithDefaultIndex(dir: File) {
  val combinedDir = staticRootFolder?.resolve(dir) ?: dir
  get("{static_path...}") {
    val relativePath = call.parameters
      .getAll("static_path")
      ?.joinToString(File.separator) ?: return@get
    val file = combinedDir.combineSafe(relativePath)
    val fallbackFile = file.combineSafe("index.html")

    val localFile = when {
      file.isFile -> file
      file.isDirectory && fallbackFile.isFile -> fallbackFile
      else -> return@get
    }

    call.respond(LocalFileContent(localFile, ContentType.defaultForFile(localFile)))
  }
}

Basically, this resolves the local file matching the requested path, serves it if it's a regular file, or serves its index.html (if present) if it's a directory. Otherwise, it delegates the error handling to Ktor (likely returning a 404).

I wrote up a slightly longer explanation of this solution here as well.