Ktor 2.0.1 Help

Serving static content

Whether we're creating a website or an HTTP endpoint, many applications need to serve files (such as stylesheets, scripts, images, etc.). While it is certainly possible with Ktor to load the contents of a file and send it in response to a request, given this is such a common functionality, Ktor simplifies the entire process for us with the static plugin.

The first step in defining a static route is to define the path under which the content should be served. For instance, if you want everything under the route assets to be treated as static content, you need to add the following to your application setup:

routing { static("assets") { } }

The next step is to define where we want the content to be served from:

  • Folders - describes how to serve static files from a local filesystem. In this case, relative paths are resolved using the current working directory.

  • Embedded application resources - describes how to serve static files from the classpath.

Folders

To demonstrate how to serve static files from a folder, let's suppose our sample project has the files directory in its root. This directory includes the following files:

files ├── index.html ├── ktor_logo.png ├── css │ └──styles.css └── js ├── script.js └── script.js.gz

In this section, we'll consider two cases of serving these files:

  • Serving all files recursively with a URL path matching a physical path.

  • Serving files/folders using customized URL paths.

Physical path

URL path matches physical path

URL path is customized

files/index.html

/index.html

/index.html or /

files/ktor_logo.png

/ktor_logo.png

/images/ktor_logo.png

files/css/styles.css

/css/styles.css

/assets/styles.css

files/js/script.js(.gz)

/js/script.js

/assets/script.js

Change the default root folder

By default, Ktor calculates a path for serving static files from a current working directory. If static files of your application is stored inside a specific folder, you can set it as a default root folder from where the content is served using the staticRootFolder property. For the files folder in the project root, the configuration looks as follows:

static("/") { staticRootFolder = File("files") }

This maps any request to / to the files physical folder. As the next step, you need to specify how to serve static files using the file or files functions.

Serve all files including in subfolders

To serve all files from the files folder recursively, you can pass the "." string to the files function:

static("/") { staticRootFolder = File("files") files(".") }

In this case, Ktor serves up any file from files as long as a URL path and physical filename match. In the next chapters, we'll take a look at how to customize URL paths.

Serve individual files

To serve individual files, use the file function. For example, to serve the files/index.html file, update configuration as follows:

static("/") { staticRootFolder = File("files") file("index.html") }

As for the Routing plugin, you can define sub-routes by nesting the static functions. The example below shows how to serve the ktor_logo.png file under the /images URL path:

static("/") { staticRootFolder = File("files") static("images") { file("ktor_logo.png") file("image.png", "ktor_logo.png") } }

Note that the file function optionally takes a second argument that allows you to map a physical filename to a virtual one. So for the example above, the ktor_logo.png image is served for requests to the following paths:

  • /images/ktor_logo.png

  • /images/image.png

Define a default file

For a specific path, we can also define the default file to be loaded using the default function. The code snippet below shows how to define index.html as the default file:

static("/") { staticRootFolder = File("files") default("index.html") }

In this case, for requests to / a Ktor server serves files/index.html.

Serve content from a folder

In addition to serving individual files, you can serve the contents from a folder. To accomplish this, you need to specify the folder name using the files function. The snippet below shows how to serve stylesheets and scripts for our sample project:

static("/") { staticRootFolder = File("files") static("assets") { files("css") files("js") } }

files("css") would then allow for any file located in the css folder to be served as static content under the given URL pattern, which in this case is assets. This means that a request to /assets/styles.css would serve the files/css/styles.css file.

Serve pre-compressed files

Ktor provides the ability to serve pre-compressed files and avoid using dynamic compression. For example, to serve pre-compressed files from the css and js folders, call files inside the preCompressed function in the following way:

static("assets") { preCompressed { files("css") files("js") } }

You can also raise the priority of one compression type over another. In the example below, Ktor tries to serve *.br files over *.gz:

static("assets") { preCompressed(CompressedFileType.BROTLI, CompressedFileType.GZIP) { files("css") files("js") } }

For example, for a request made to /assets/script.js, Ktor tries to serve js/script.js.br first.

Embedded application resources

To demonstrate how to serve static files from application resources, let's suppose our sample project has the static package in the resources directory. This package includes the following files:

static ├── index.html ├── ktor_logo.png ├── css │ └──styles.css └── js └── script.js

In this section, we'll consider two cases of serving these files:

  • Serving all resources recursively with a URL path matching a physical path.

  • Serving resources/resource folders using customized URL paths.

Physical path

URL path matches physical path

URL path is customized

static/index.html

/index.html

/index.html or /

static/ktor_logo.png

/ktor_logo.png

/images/ktor_logo.png

static/css/styles.css

/css/styles.css

/assets/styles.css

static/js/script.js(.gz)

/js/script.js

/assets/script.js

Change the default resource package

By default, Ktor calculates a path for serving static resources from a resources root directory. If static files of your application is stored inside a specific resource package, you can set it as a default package from where the content is served using the staticBasePackage property. For example, for the static package inside the resources folder, the configuration looks as follows:

static("/") { staticBasePackage = "static" }

This maps any request to / to the static package. As the next step, you need to specify how to serve static resources using the resource or resources functions.

Serve all resources including in subfolders

To serve all files from the static folder recursively, you can pass the "." string to the resources function:

static("/") { staticBasePackage = "static" resources(".") }

In this case, Ktor serves up any file from static as long as a URL path and physical filename match. In the next chapters, we'll take a look at how to customize URL paths.

Serve individual resources

To serve individual resources, use the resource function. For example, to serve the static/index.html file, update configuration as follows:

static("/") { staticBasePackage = "static" resource("index.html") }

As for the Routing plugin, you can define sub-routes by nesting the static functions. The example below shows how to serve the ktor_logo.png file under the /images URL path:

static("/") { staticBasePackage = "static" static("images") { resource("ktor_logo.png") resource("image.png", "ktor_logo.png") } }

Note that the resource function optionally takes a second argument that allows you to map a physical filename to a virtual one. So for the example above, the ktor_logo.png image is served for requests to the following paths:

  • /images/ktor_logo.png

  • /images/image.png

Ktor automatically looks up the content type of file based on its extension and sets the appropriate Content-Type header.

Define a default resource

For a specific path, we can also define the default resource to be loaded using the defaultResource function. The code snippet below shows how to define index.html as the default resource:

static("/") { staticBasePackage = "static" defaultResource("index.html") }

In this case, for requests to / a Ktor server serves static/index.html.

Serve content from a resource folder

In addition to serving individual files, you can serve the contents from a resource folder. To accomplish this, you need to specify the resource folder name using the resources function. The snippet below shows how to serve stylesheets and scripts for our sample project:

static("/") { staticBasePackage = "static" static("assets") { resources("css") resources("js") } }

resources("css") would then allow for any file located in the css resource folder to be served as static content under the given URL pattern, which in this case is assets. This means that a request to /assets/styles.css would serve the files/css/styles.css file.

Handle errors

If the requested content is not found, Ktor will automatically respond with a 404 Not Found HTTP status code. For more information about personalizing error handling, see Status pages.

Examples

Example applications that serve static files using both folders and resources can be found below:

package com.example import io.ktor.server.application.* import io.ktor.server.http.content.* import io.ktor.server.routing.* import java.io.* fun Application.module() { routing { static("/") { staticRootFolder = File("files") file("index.html") default("index.html") static("images") { file("ktor_logo.png") file("image.png", "ktor_logo.png") } static("assets") { files("css") files("js") } } } }
package com.example import io.ktor.server.application.* import io.ktor.server.http.content.* import io.ktor.server.routing.* fun Application.module() { routing { static("/") { staticBasePackage = "static" resource("index.html") defaultResource("index.html") static("images") { resource("ktor_logo.png") resource("image.png", "ktor_logo.png") } static("assets") { resources("css") resources("js") } } } }

You can find the full examples here:

Last modified: 13 May 2022