Ktor 2.0.3 Help

Plugins

A typical request/response pipeline in Ktor looks like the following:

Request Response Pipeline

It starts with a request, which is routed to a specific handler, processed by our application logic, and finally responded to.

Add functionality with Plugins

Many applications require common functionality that is out of scope of the application logic. This could be things like serialization and content encoding, compression, headers, cookie support, etc. All of these are provided in Ktor by means of what we call Plugins.

If we look at the previous pipeline diagram, Plugins sit between the request/response and the application logic:

Plugin pipeline

As a request comes in:

  • It is routed to the correct handler via the routing mechanism

  • before being handed off to the handler, it goes through one or more Plugins

  • the handler (application logic) handles the request

  • before the response is sent to the client, it goes through one or more Plugins

Routing is a Plugin

Plugins have been designed in a way to offer maximum flexibility, and allow them to be present in any segment of the request/response pipeline. In fact, what we've been calling routing until now, is nothing more than a Plugin.

Routing as a Plugin

Add Plugin dependency

Most of the plugins require a specific dependency. For example, the CORS plugin requires adding the ktor-server-cors artifact in the build script:

implementation("io.ktor:ktor-server-cors:$ktor_version")
implementation "io.ktor:ktor-server-cors:$ktor_version"
<dependency> <groupId>io.ktor</groupId> <artifactId>ktor-server-cors-jvm</artifactId> <version>${ktor_version}</version> </dependency>

As an alternative, you can use the ktor-server artifact containing all Ktor server plugins:

implementation("io.ktor:ktor-server:$ktor_version")
implementation "io.ktor:ktor-server:$ktor_version"
<dependency> <groupId>io.ktor</groupId> <artifactId>ktor-server-jvm</artifactId> <version>${ktor_version}</version> </dependency>

Install Plugins

Plugins are generally configured during the initialization phase of the server using the install function which takes a Plugin as a parameter. Depending on the way you used to create a server, you can install a plugin inside the embeddedServer call ...

import io.ktor.server.application.* import io.ktor.server.plugins.cors.* import io.ktor.server.plugins.compression.* // ... fun main() { embeddedServer(Netty, port = 8080) { install(CORS) install(Compression) // ... }.start(wait = true) }

... or a specified module:

import io.ktor.server.application.* import io.ktor.server.plugins.cors.* import io.ktor.server.plugins.compression.* // ... fun Application.module() { install(CORS) install(Compression) // ... }

In addition to intercepting requests and responses, Plugins can have an option configuration section which is configured during this step.

For instance, when installing Cookies we can set certain parameters such as where we want Cookies to be stored, or their name:

install(Sessions) { cookie<MyCookie>("MY_COOKIE") }

Install Plugins for specific routes

In Ktor, you can install plugins not only globally but also to a specific routes. This might be useful if you need different plugin configurations for different application resources. For instance, the example below shows how to add specific caching headers configurations for specific routes (/index and /profile):

routing { route("/index") { install(CachingHeaders) { options { call, content -> CachingOptions(CacheControl.MaxAge(maxAgeSeconds = 3600)) } } } route("/profile") { install(CachingHeaders) { options { call, content -> CachingOptions(CacheControl.NoStore(visibility = CacheControl.Visibility.Private)) } } } }

Note that the following rules are applied to several installations of the same plugin:

  • Configuration of a plugin installed to a specific route overrides its global configuration.

  • Routing merges installations for the same route, and the last installation wins. For example, for such an application ...

    routing { route("index") { install(CachingHeaders) { // First configuration } get("a") { // ... } } route("index") { install(CachingHeaders) { // Second configuration } get("b") { // ... } } }

    ... both calls to /index/a and /index/b are handled by only second installation of the plugin.

Default, available, and custom Plugins

By default, Ktor does not activate any Plugin, and it's up to us as developers to install the functionality our application need.

Ktor does however provide a variety of Plugins that ship out of the box. We can see a complete list of these either on the Project Generator Site or in the IntelliJ IDEA Wizard. In addition, we can also create our own custom Plugins.

Last modified: 28 June 2022