Ktor 3.0.2 Help

Serving static content

Whether you're creating a website or an HTTP endpoint, your application will likely need to serve files, such as stylesheets, scripts, or images. While it is certainly possible with Ktor to load the contents of a file and send it in a response to a client, Ktor simplifies this process by providing additional functions for serving static content.

With Ktor, you can serve content from folders, ZIP files, and embedded application resources.

Folders

To serve static files from a local filesystem, use the staticFiles() function. In this case, relative paths are resolved using the current working directory.

routing { staticFiles("/resources", File("files")) }

In the example above, any request from /resources is mapped to the files physical folder in the current working directory. Ktor recursively serves up any file from files as long as a URL path and a physical filename match.

For the full example, see static-files.

ZIP files

To serve static content from a ZIP file, Ktor provides the staticZip() function. This allows you to map requests directly to the contents of a ZIP archive, as shown in the example below:

routing { staticZip("/", "", Paths.get("files/text-files.zip")) }

In this example, any request from the root URL / is mapped directly to the contents of the ZIP file text-files.zip.

Auto-reloading support

The staticZip() function also supports automatic reloading. If any changes are detected in the ZIP file's parent directory, the ZIP file system is reloaded on the next request. This ensures that the served content remains up-to-date without requiring a server restart.

For the full example, see static-zip.

Resources

To serve content from the classpath, use the staticResources() function.

routing { staticResources("/resources", "static") }

This maps any request from /resources to the static package in application resources. In this case, Ktor recursively serves up any file from the static package as long as a URL path and a path to resource match.

For the full example, see static-resources.

Additional configuration

Ktor provides more configurations to static files and resources.

Index file

If a file with the name index.html exists, Ktor will serve it by default when the directory is requested. You can set a custom index file using the index parameter:

staticResources("/custom", "static", index = "custom_index.html")

In this case, when /custom is requested, Ktor serves /custom_index.html.

Pre-compressed files

Ktor provides the ability to serve pre-compressed files and avoid using dynamic compression. To use this functionality, define the preCompressed() function inside a block statement:

staticFiles("/", File("files")) { preCompressed(CompressedFileType.BROTLI, CompressedFileType.GZIP) }

In this example, for a request made to /js/script.js, Ktor can serve /js/script.js.br or /js/script.js.gz.

HEAD requests

The enableAutoHeadResponse() function allows you to automatically respond to a HEAD request for every path inside a static route that has a GET defined.

staticResources("/", "static"){ enableAutoHeadResponse() }

Default file response

The default() function provides the ability to reply with a file for any request inside static route that has no corresponding file.

staticFiles("/", File("files")) { default("index.html") }

In this example when the client requests a resource that doesn't exist, the index.html file will be served as a response.

Content type

By default, Ktor tries to guess value of the Content-Type header from the file extension. You can use the contentType() function to set the Content-Type header explicitly.

staticFiles("/files", File("textFiles")) { contentType { file -> when (file.name) { "html-file.txt" -> ContentType.Text.Html else -> null } } }

In this example, the response for file html-file.txt will have Content-Type: text/html header and for every other file default behaviour will be applied.

Caching

The cacheControl() function allows you to configure the Cache-Control header for HTTP caching.

fun Application.module() { routing { staticFiles("/files", File("textFiles")) { cacheControl { file -> when (file.name) { "file.txt" -> listOf(Immutable, CacheControl.MaxAge(10000)) else -> emptyList() } } } } } object Immutable : CacheControl(null) { override fun toString(): String = "immutable" }

Excluded files

The exclude() function allows you to exclude files from being served. When excluded files are requested by the client, the server will respond with a 403 Forbidden status code.

staticFiles("/files", File("textFiles")) { exclude { file -> file.path.contains("excluded") } }

File extensions fallbacks

When a requested file is not found, Ktor can add the given extensions to the file name and search for it.

staticResources("/", "static"){ extensions("html", "htm") }

In this example, when /index is requested, Ktor will search for /index.html and serve the found content.

Custom modifications

The modify() function allows you to apply custom modification to a resulting response.

staticFiles("/", File("files")) { modify { file, call -> call.response.headers.append(HttpHeaders.ETag, file.name.toString()) } }

Handle errors

If the requested content is not found, Ktor will automatically respond with a 404 Not Found HTTP status code.

To learn how to configure error handling, see Status Pages.

Last modified: 16 October 2024