The Ktor Blog : Building Asynchronous Servers and Clients in Kotlin | The JetBrains Blog https://blog.jetbrains.com Developer Tools for Professionals and Teams Thu, 20 Apr 2023 10:19:36 +0000 en-US hourly 1 https://blog.jetbrains.com/wp-content/uploads/2023/02/cropped-icon-512-32x32.png The Ktor Blog : Building Asynchronous Servers and Clients in Kotlin | The JetBrains Blog https://blog.jetbrains.com 32 32 Ktor 2.3.0 Released https://blog.jetbrains.com/ktor/2023/04/18/ktor-2-3-0-released/ Tue, 18 Apr 2023 13:38:58 +0000 https://blog.jetbrains.com/?post_type=ktor&p=343348 We are pleased to announce the release of Ktor 2.3.0. This update brings numerous new features and improvements to the Ktor ecosystem. The following sections provide a brief overview of the major changes in this release:

Core Improvements

Explicit type for WebSockets ContentNegotiation Plugin

The WebSocket ContentNegotiation plugin now supports specifying explicit type:

client.webSocket("ws://localhost:8080/echo") {
    val originalData: Any = Data("hello")
    sendSerialized(originalData, typeInfo<Data>())
    val received = receiveDeserialized<Data>(typeInfo<Data>())

    assertEquals(originalData, received)
}

It can be helpful if reified parameters are not available.

Structured Concurrency Support for Sockets

The Socket implementation from ktor-network is a CoroutineScope now. It means it supports the cancel() operation to terminate the connection immediately.

The close() continues working as a graceful shutdown and will wait for all pending operations to complete.

Dropping the JS Legacy Configuration

The upcoming Kotlin 1.9.0 release will remove the legacy JS compiler. Starting from Ktor 2.3.0, the legacy compiler is no longer supported. Please consider migrating to the new IR compiler.

Server

Regular Expression Support in Routing

Ktor now allows the use of regular expressions when defining routes. With regex routing, you can match a complex route and capture route parameters with ease:


routing {
    get(Regex("^(?<name>.+)$")) {
        val name = call.parameters["name"]
        call.respondText("Hello, $name!")
    }
}

Will work as:

$ curl http://0.0.0.0:8081/Leonid
Hello, Leonid!

You can learn more from the documentation.

Static Content API Cleanup

The Static Content API has been refined and streamlined for a more user-friendly experience. This time we focused on the most common cases and made a simple API for them:

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

Will serve all files from the files directory under the /static path.

And we can also serve files from the resources:

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

It also configures serving index.html as a default file and supports features like precompression (even for resources), caching headers, content-type detection, etc.

To learn more about the Static Content API, please refer to the documentation.

Old API is still available and will be supported.

Support for 100 Continue for the CIO

The CIO engine now supports the 100 Continue status. It works out of the box and requires no additional configuration.

Multiple Configuration File Support

Configuration management has been simplified by allowing the use of multiple files. You can pass multiple configuration files using -config CLI option. The configuration files will be loaded and merged in order.

Please read more about the Configuration Files in the documentation.

Jetty 11 and Tomcat 10 Support

For projects already containing Jetty or Tomcat dependencies with major updates, Ktor 2.3.0 adds support for Jetty 11 and Tomcat 10 server implementations. They are delivered as separate dependencies:

dependencies {
    implementation("io.ktor:ktor-server-jetty-jakarta:2.3.0")
    implementation("io.ktor:ktor-server-tomcat-jakarta:2.3.0")
    implementation("io.ktor:ktor-server-servlet-jakarta:2.3.0")
}

If you need to use the new version, please change the dependency to the jakarta version. No migration is required.

Client

Expect header and 100 Continue

The Expect header is now supported by the client. If you want to use it, please add Expect header to the request:

client.post("http://localhost:8080/upload") {
    header("Expect", "100-continue")
    body = "Hello, World!"
}

Sensitive Header Sanitizing in Logging Plugin

The Logging plugin now supports sanitizing sensitive headers. It can be configured using sanitizeHeader function:

val client = HttpClient {
    install(Logging) {
        sanitizeHeader("<secret>") { it == HttpHeaders.Authorization }
    }
}

This configuration will replace the header value with a placeholder for all Authorization headers.

Static Linking of libcurl for mingwx64 Target

To simplify version management, libcurl library has been linked statically to ktor-client-curl. Installing libcurl on the system is no longer required to use the dependency.

Apache 5 and Jetty 11 Support

The new versions of Apache and Jetty were added as separate dependencies:

dependencies {
    implementation("io.ktor:ktor-client-jetty-jakarta:2.3.0")
    implementation("io.ktor:ktor-client-apache5:2.3.0")
}

If you need to use the new version, please change the dependencies accordingly. No migration is required.

New Project Wizard and Sample Updates

The New Project Wizard has been updated with new Exposed and Postgres plugins, and new samples have been added to facilitate a more engaging Ktor experience.

The full list of changes can be found on GitHub.

Special Thanks to Our Contributors

A huge thank you to all contributors for their time, effort, and expertise in improving Ktor. Special thanks to chedabob, ay4toh5i, lkurcius, InsanusMokrassar, brianguertin, sproctor, nesk, Rattenkrieg, morki, pull-vert, Sebmaster.

Try it out

We invite you to discover the enhancements in Ktor 2.3.0 and share your invaluable feedback with us. If you are new to Ktor, you can create a new project using our New Project Generator. For reporting issues or suggesting new features, please visit YouTrack.

Thank you for your continued support!

]]>
https://blog.jetbrains.com/zh-hans/ktor/2023/04/18/ktor-2-3-0-released/ https://blog.jetbrains.com/ko/ktor/2023/04/18/ktor-2-3-0-released/
Ktor 2023 Roadmap https://blog.jetbrains.com/ktor/2022/12/16/ktor-2023-roadmap/ Fri, 16 Dec 2022 11:14:16 +0000 https://blog.jetbrains.com/?post_type=ktor&p=307046 We’ve been working on defining our roadmap for Ktor for 2023, and much like we did for 2022, we’d like to share our plans with you and what we have in store.

One of the things we’re planning on doing this year is releasing 3.0.0. While major versions generally indicate a breaking change, most of the changes are in regards to API and packaging. In particular

  • We’re going to release the new simplified routing API that we’ve been working on.
  • We’re switching to Tomcat 11, Jetty 11, and upgrading Apache Client to support version 5.
  • We’re extracting the IO functionality into a separate library. This is a long-standing task that we’ve been working on gradually, and aim to finalize in 2023.

Long standing issues

Talking about long-standing issues, we went from the 150 issues that we had in 2022, down to 17. We will continue to address these until we reach zero. In addition we managed to do some housekeeping, reducing the number of flaky tests to three. We also aim to tackle these last remaining ones this year.

Bootstrapping and onboarding

One of our goals continues to be simplifying boilerplate code and getting applications up and running with little effort. In this regard, we made some progress in 2022, including easier bootstrapping of not only server, but also client applications. Next year we want to continue down this path and focus on areas such as:

  • Getting up and running easily with frameworks and libraries for data access. In particular we’ll be working on simplifying things for Exposed, JDBC, and MongoDB
  • Working on new plugins for metrics, telemetry, retrofit, and Zipkin amongst others.
  • Simplifying support for authorization and authentication. Providing end-to-end support for database authentication and session management, as well as role-based authorization.

Tooling

We’re going to provide a bunch of new functionality when it comes to tooling support including updates to our CLI clients as well as our IDE support. In particular we’ll be

  • Route support, including refactoring such as extracting routes, generation of routes, as well as improved navigation and route look-up.
  • Improved completion for hooks and other areas of Ktor code.
  • Support for debugging microservices, providing transparent stacktraces between client and server requests.

And more…

In addition to the higher-level areas of focus and some key functionality in each of these, we plan to work on many more things, not just those listed. As always, our issue tracker provides you the latest information on our progress.

We’re very excited about the road ahead for 2023 and we’ll continue to work on making Ktor a truly pleasurable framework to create your client and server applications!

Finally, we want to thank you for all the feedback you’ve provided, not only on YouTrack and our Slack channel, but also for filling out our annual survey! All these channels are important for us to help shape the direction of Ktor and make sure that what we’re working on is aligned with the needs of our users.

]]>
Ktor 2.2.1 (and 2.2.0) released https://blog.jetbrains.com/ktor/2022/12/08/ktor-2-2-0-released/ Thu, 08 Dec 2022 06:00:00 +0000 https://blog.jetbrains.com/?post_type=ktor&p=305095
Important: Yesterday we released 2.2.0 to Maven Central, but immediately after we noticed a critical issue of AtomicFu that needed addressing, and as a consequence shortly after we pushed 2.2.1. As such, if you are using 2.2.0, we strongly advise moving to 2.2.1.

We’ve released Ktor 2.2.0/2.2.1, which introduces many new features and fixes. Moreover, with the latest 2022.3 IntelliJ IDEA version, the Ktor plugin lets you generate OpenAPI documentation for server-side Ktor applications using the dedicated intention action.

For guidance about migrating your Ktor project to the new 2.2.0 version, see these instructions.
If you’re new to Ktor, create your first application today!

Generating OpenAPI

To generate an OpenAPI specification for a Ktor application, place the caret at the embeddedServer function call, press Alt+Enter, and choose Generate OpenAPI documentation for current module. IntelliJ IDEA will generate the paths for all application endpoints defined using either string path patterns or type-safe routes.

You can learn more about this feature from the documentation: Ktor | OpenAPI.

Note: The following 2 known issues in the OpenAPI generator will be fixed in the next IntelliJ IDEA patch release: KTOR-5194 and KTOR-5195.

Server

Serving OpenAPI

Ktor 2.2.0 allows you to generate and serve Swagger UI for your project based on the existing OpenAPI specification. For example, if your project contains the OpenAPI specification at resources/openapi/documentation.yaml, you can serve Swagger UI for this specification by calling swaggerUI with the following parameters:

routing {
    swaggerUI(path = "swagger", swaggerFile = "openapi/documentation.yaml")
}

Then you can run the application, open the http://0.0.0.0:8080/swagger page, and interact with the API resources using the generated Swagger UI.

To learn more about how to set up this plugin, see the Swagger UI topic. Similarly, you can render a web page with OpenAPI documentation using the OpenAPI plugin.

Rate limiting

In this release, we’ve added a new RateLimit plugin, which allows you to set rate limiting for incoming requests. For example, you can enable rate limiting globally as shown below:

install(RateLimit) {
    global {
        rateLimiter(limit = 5, refillPeriod = 60.seconds)
    }
}

You can also register a rate-limiting provider with the specified name:

install(RateLimit) {
    register(RateLimitName("protected")) {
        rateLimiter(limit = 30, refillPeriod = 60.seconds)
    }
}

And you can apply the provider to a specific route:

routing {
    rateLimit(RateLimitName("protected")) {
        get("/protected-api") {
            val requestsLeft = call.response.headers["X-RateLimit-Remaining"]
            call.respondText("Welcome to protected API! $requestsLeft requests left.")
        }
    }
}

You can learn more from the Rate limiting help topic.

Authentication

Bearer authentication

As you might know, the Ktor server already supports the Bearer authentication scheme as part of OAuth or JWT. With this release, you can also provide custom logic for authorizing bearer tokens using the dedicated bearer authentication provider, which allows you to check the token sent by the client:

install(Authentication) {
    bearer("auth-bearer") {
        realm = "Access to the '/' path"
        authenticate { tokenCredential ->
            if (tokenCredential.token == "abc123") {
                UserIdPrincipal("jetbrains")
            } else {
                null
            }
        }
    }
}

We’d like to thank our community contributor oharaandrew314 for their contribution in this area.

For more details, see the Bearer authentication help topic.

Nested authentication improvements

The Authentication plugin allows you to define the authorization scope for resources by using the authenticate function. In older versions of Ktor, if you had several nested calls of the authenticate method for different providers, the client had to provide authentication data for any provider. With v2.2.0, you can define a strategy for resolving nested authentication providers. This might be useful if the client must provide authentication data for all registered providers. In the code snippet below, only a user that passes session authentication can try to access the /admin route using basic authentication:

routing {
    authenticate("auth-session", strategy = AuthenticationStrategy.Required) {
        get("/hello") {
            // ...
        }
        authenticate("auth-basic", strategy = AuthenticationStrategy.Required) {
            get("/admin") {
                // ...
            }
        }
    }
}

We are planning to make the AuthenticationStrategy.Required strategy the default in the future to make the behavior of nested authentication providers clearer.

Digest authentication

We’ve added the ability to map the credentials to a custom principal for the Digest provider. In the example below, validate returns a CustomPrincipal instance in case of successful authentication.

fun Application.main() {
    install(Authentication) {
        digest("auth-digest") {
            // ...
            validate { credentials ->
                if (credentials.userName.isNotEmpty()) {
                    CustomPrincipal(credentials.userName, credentials.realm)
                } else {
                    null
                }
            }
        }
    }
}

Serialization

With this release, we’ve added the ProtoBuf serializer for serializing/deserializing data objects. To start using ProtoBuf, add the ktor-serialization-kotlinx-protobuf dependency to the build script and install the serializer as follows:

import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.protobuf.*

install(ContentNegotiation) {
    protobuf()
}

You can also use the ProtoBuf serializer with WebSockets:

import kotlinx.serialization.protobuf.*

install(WebSockets) {
    contentConverter = KotlinxWebsocketSerializationConverter(ProtoBuf)
}

Custom plugins configuration

Ktor 2.2.0 lets you configure custom plugins in a configuration file. For example, the application.yaml configuration file contains a configuration for a custom plugin in the http.custom_header group:

http:
  custom_header:
    header_name: X-Another-Custom-Header
    header_value: Some value

You can access the configuration values as follows:

class CustomHeaderConfiguration(config: ApplicationConfig) {
    var headerName: String = config.tryGetString("header_name") ?: "Custom-Header-Name"
    var headerValue: String = config.tryGetString("header_value") ?: "Default value"
}

Finally, set the configurationPath parameter to http.custom_header when creating a plugin:

val CustomHeaderPluginConfigurable = createApplicationPlugin(
    name = "CustomHeaderPluginConfigurable",
    configurationPath = "http.custom_header",
    createConfiguration = ::CustomHeaderConfiguration
) {
    // …
}

For the complete code example, visit the Configuration in a file help section.

Native server

We’ve made the following improvements to the Native server in this release:

  • The Native server now supports the Sessions plugin.
  • You can change the logging level on the Native server by using the KTOR_LOG_LEVEL environment variable. Enabling route tracing in this way can help you understand why some routes are not being executed.

TLS and certificates

Generating certificates

With this release, the buildKeyStore method provides more flexibility for generating self-signed certificates. For instance, you can now specify which domains are allowed in a test certificate:

val keyStore = buildKeyStore {
    certificate("sampleAlias") {
        password = "foobar"
        domains = listOf("127.0.0.1", "0.0.0.0", "localhost")
    }
}

We’d like to thank joffrey-bion for contributing to this improvement.

Configuring TLS versions

The enabledProtocols property available inside sslConnector now allows you to block the use of TLS 1.0 and 1.1.

val environment = applicationEngineEnvironment {
    // ...
    sslConnector(
        // ...
        enabledProtocols = listOf("TLSv1.3", "TLSv1.2")
    }
}

We’d like to thank joreilly for contributing to this improvement.

Obtaining connection details

This release also brings improvements to resolving connection details such as hostname and port. For example, before v2.2.0, you could get the hostname or port to which the request was made using the RequestConnectionPoint.host and RequestConnectionPoint.port properties:

get("/hello") {
    val originHost = call.request.origin.host
    val originPort = call.request.origin.port
}

With this release, these properties have been deprecated and replaced with serverHost and serverPort. We’ve also added the localHost/localPort properties that return the hostname or port on which the request was received. Refer to the Original request information section to learn more.

Other improvements

This release also adds other improvements for TLS and certificates, including test server lifecycle management, logging debug information for routing and other plugins, and other bug fixes and features.

Client

New custom plugins API

In addition to simplifying the extensibility API for the Ktor server, we’ve implemented a new API for creating custom client plugins. Instead of intercepting pipelines, you can now access different stages of handling requests and responses by using a set of handlers, such as onRequest, onResponse, and so on.

The code snippet below shows how to create a plugin that adds a predefined custom header to each request:

import io.ktor.client.plugins.api.*

val CustomHeaderPlugin = createClientPlugin("CustomHeaderPlugin") {
    onRequest { request, _ ->
        request.headers.append("X-Custom-Header", "Default value")
    }
}

To learn more, see the Custom plugins topic in our documentation.

Persistent HttpCache

We’ve implemented the ability to implement persistent caching for the Ktor client. To do this, you can use the CacheStorage interface or its FileStorage implementation on JVM. The code snippet below shows how to do the latter:

val client = HttpClient(CIO) {
    install(HttpCache) {
        val cacheFile = Files.createDirectories(Paths.get("build/cache")).toFile()
        publicStorage(FileStorage(cacheFile))
    }
}

Note that the publicStorage and privateStorageproperties have been deprecated in favor of the respective methods.

Serialization

The ProtoBuf serializer is also available for the Ktor client. The following snippet shows how to enable ProtoBuf for the ContentNegotiation plugin:

import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.protobuf.*

val client = HttpClient(CIO) {
    install(ContentNegotiation) {
        protobuf()
    }
}

The serializer is also available for WebSockets.

Native windows HTTP client

This release adds the WinHttp native engine that targets Windows-based operating systems and supports WebSockets. To learn how to configure it, see the WinHttp doc section.

Sample updates

As you might know, the ktor-samples repository contains a collection of ready-to-use samples for Ktor. We’ve migrated these samples to the latest version of Ktor API, in particular, replaced the Location plugin usages to Resources and updated tests to a new testing API implemented in v2.0.0. You can browse through these samples to understand different ways to accomplish things in Ktor.

Docs infrastructure

The final thing we want to mention is the latest changes we’ve made to our documentation infrastructure. Ktor documentation lives in a separate GitHub repository: https://github.com/ktorio/ktor-documentation.

To build our documentation, we now use Writerside, a new tool from JetBrains for creating and publishing docs. It uses the docs-as-code approach and provides automatic quality checks, natural language assistance, live preview, and other useful features. If you want to try this tool, feel free to enroll in the Writerside Early Access Program at https://jb.gg/writerside.

Happy developing!
The Ktor team

]]>
Ktor 2.1.0 Released and It Comes With Goodies! https://blog.jetbrains.com/ktor/2022/08/12/ktor-2-1-0-released-and-it-comes-with-goodies/ Fri, 12 Aug 2022 09:17:22 +0000 https://blog.jetbrains.com/?post_type=ktor&p=269160 We’ve just released Ktor 2.1.0, and in addition to the new features and bug fixes, we have a few new things we’d love for you to try out. In particular, we are releasing betas of three new tools:

  • Command Line tool
  • Yeoman Generator
  • Gradle Deployment Plugin
  • YAML configuration support

Let’s take a look at each of these individually. 

Native Command Line Tool

Ktor provides two ways to simplify creating new application templates – IntelliJ IDEA or start.ktor.io

We’ve now extended this by providing a command line tool built in Kotlin/Native. However, beyond just generating a Ktor server application for you, it also takes care of downloading a JDK if your system does not have one installed. This is ideal for folks who are new to the JVM.

To create a new project, simply type:

ktor generate {projectName}

Once completed (which will also include downloading JDK/Gradle if necessary), it will build the project.

All that’s left to do is run it! 

The tool is currently available for macOS and Linux. Windows support will come later on. 

For macOS you can download it directly from the release page or install it via brew with:

brew tap ktorio/ktor

brew install --build-from-source ktor

On Linux we’re working on trying to get it published to Snap. In the meantime you can use the release page.

The command line tool does not currently provide the option to customize your project, but the next thing we’re going to show you does!

Yeoman Generator

Similar to the command line client, we’ve also added Yeoman support. Yeoman is a command line tool that allows you to easily generate scaffolding for a variety of projects. Ktor is now one of these!

If you do not have Yeoman installed, make sure you first install node/npm (compatible with versions above 14.0.0). Once you have that, you can run:

npm install -g yo

This installs Yeoman globally on your system. Next step is to install the Ktor generators:

npm install -g generator-ktor

Once installed, you can simply create a new project directory and run the generator using:

yo ktor

It will prompt you for a series of inputs:

Then it will generate the project. This time it will automatically run it for you, too! 

Gradle Deployment Plugin

One of our goals with Ktor is to make the overall development experience as smooth and enjoyable as possible. Of course, people rarely develop an application and do not deploy it. 

To this end, we’ve recently released a beta of our new Gradle plugin for deployment (note that newly created projects using the wizards will add this plugin by default). You can now define how you would like your Ktor application to be deployed in a Gradle file:

ktor {
    docker {
        jreVersion.set(JreVersion.JRE_17)
        localImageName.set("sample-docker-image")
        imageTag.set("0.0.1-preview")

        externalRegistry.set(
            DockerImageRegistry.dockerHub(
                appName = provider { "ktor-app" },
                username = providers.environmentVariable("DOCKER_HUB_USERNAME"),
                password = providers.environmentVariable("DOCKER_HUB_PASSWORD")
            )
        )
    }
}

The plugin provides several new tasks allowing you to build, run, and publish Docker images, as well as work with FatJars, with GraalVM native images in the works. 

ktor {
    fatJar {
        archiveFileName.set("fat.jar")
    }
}

While it is currently only available for Gradle, the plan is to provide Maven support as well. For information about the list of tasks offered, check out the notes on GitHub. You can also find more details in the Ktor documentation, both about fat jars and about Docker.

YAML configuration support

In addition to configuring Ktor applications using code or HOCON, you can now use YAML, which is also available for Ktor native server applications. Take the following HOCON configuration:

ktor {
    deployment {
        port = 8080
    }
    application {
        modules = [ com.example.ApplicationKt.module ]
    }
}

In YAML, the equivalent would be:

ktor:
    deployment:
        port: 8080
    application:
        modules:
            - com.example.ApplicationKt.module

You can find out more about YAML configuration in the documentation.

We’d love for you to try these new tools out and give us some feedback! 

]]>
Ktor 2.0 Released https://blog.jetbrains.com/ktor/2022/04/11/ktor-2-0-released/ Mon, 11 Apr 2022 13:31:27 +0000 https://blog.jetbrains.com/?post_type=ktor&p=237548 We’re extremely excited to announce the release of Ktor 2.0. We have been working on this version for approximately one year and happy to finally get it out the door! 

Ktor 2.0 introduces many new features, but a major version which means that there are breaking changes, it has allowed us the opportunity to perform some maintenance work and get rid of legacy decisions. Don’t worry though – despite the breaking changes, we’ve tried our best to minimize these and also aid with some tooling that hopefully can help with automated migrations. More on that later though, first let’s take a look at some of the new functionality

Ktor Server

Simplified Extensibility

We’ve always built Ktor in mind for extensibility. Initially called Features, and now renamed to Plugins, all of the features (now you see why we renamed it) that Ktor offers are built using plugin architecture. The problem we encountered though was that for some folks it was hard to understand the architecture model behind it. In 2.0 we drastically simplified the extensibility API making the creation of plugins significantly easier. 

Take a look at the following API code from 1.x

companion object Feature : ApplicationFeature<ApplicationCallPipeline, CustomHeader.Configuration, CustomHeader> {
    override val key = AttributeKey<CustomHeader>("CustomPlugin")
    override fun install(pipeline: ApplicationCallPipeline, configure: Configuration.() -> Unit): CustomHeader {
       val configuration = Configuration().apply(configure)

       val feature = CustomHeader(configuration)

       pipeline.intercept(ApplicationCallPipeline.Call) {

            feature.intercept(this)
        }

       return feature
    }
}

The equivalent in 2.0 is

val myCustomPlugin = createApplicationPlugin("CustomPlugin") {
    onCall {

    }

    onCallReceive {

    }

    onCallRespond {

    }
}

Most of the existing plugins have been converted to use the new API and we’re pretty sure that the majority of scenarios can be covered. For more details, checkout the conversion for the `CustomHeader` plugin from the old to the new API, as well as the documentation for plugin development.

We have a lot more planned when it comes to extensibility, including facilities to easily publish and consume plugins from a marketplace! 

Native support

On the server side, we now support Kotlin/Native in addition to GraalVM (which was already supported from 1.6), meaning that you have two options when it comes to self-contained server applications. 

In regards to Kotin/Native support, currently it is limited to using CIO as an engine and we are continuing to work in areas of performance. We do recommend however using the new Kotlin/Native memory model. 

Other server improvements

We also have a series of smaller improvements for Ktor server including random port support

fun main() {
    embeddedServer(Netty, port = 0) {
        configureRouting()
    }.start(wait = true)
}

as well as improved testing API, type-safe routing, XML Serialization, subroutes for plugins, and 60+ bug fixes and other features

Ktor Client

Simplified APIs

Continuing with the simplification of APIs, in the case of Ktor client, we’ve introduced new APIs to deal with common HTTP requests

val result = client.post("http://127.0.0.1:$port/") {

}
result.bodyAsText()

We’ve gotten rid of the generic post<T>, get<T> methods. Everything now returns an `HttpResponse` where you can access the body (with `bodyAsText`, `bodyAsChannel`) as well as the headers.

Retries

We now have built-in support for retries, including adjustment of time between retries

val client = HttpClient(CIO) {
    install(HttpRequestRetry) {
        maxRetries = 5
        retryIf { request, response ->
            !response.status.isSuccess()
        }
        retryOnExceptionIf { _, cause ->
            cause is NetworkError
        }
        delayMillis { retry ->
            retry * 3000L
        } // retries in 3, 6, 9, etc. seconds
    }
}

Content Negotiation

If you’ve been using the content negotiation feature in the server, you’re probably already familiar with what it is and how it works. Essentially it’s the ability for a client and server to negotiate the different types of content that can be requested and served. The negotiation aspect of it was only available up to now for the server. We’ve now brought this to the client too!

val client = HttpClient(CIO) {
    install(ContentNegotiation) {
    }
}

This plugin effectively replaced the `JsonFeature`. 

Other client improvements

In addition to the above, the client also includes shortcut APIs for authentication such as `basic()` and `bearer()` helper functions, as well as interceptors at request level, a new metrics plugin, XML serialization, and many bug fixes and other features.

Migrating to Ktor 2.0

An issue we’ve had with Ktor has been the inconsistency of module and package names. Some had the prefix server, while others did not. Some worked for server and client, while not having any prefix whatsoever. In addition, we had multiple plugins in a single module, making discovery cumbersome. 

The change to a major version has provided us the opportunity to introduce some consistent naming conventions when it comes to modules and packages. Moving forward, anything that is only server, will have the server prefix. Anything that is client, will have the client prefix. Common packages will have the no prefix. In addition, plugins are now contained in their own modules. 

import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.client.request.*
import io.ktor.client.statement.*
import io.ktor.http.content.*
import io.ktor.util.*
import io.ktor.utils.io.*

And the same goes for module names 

implementation "io.ktor:ktor-server-auth:$ktor_version"
implementation "io.ktor:ktor-server-default-headers:$ktor_version"
implementation "io.ktor:ktor-server-sessions:$ktor_version"
implementation "io.ktor:ktor-server-status-pages:$ktor_version"
implementation "io.ktor:ktor-server-cors:$ktor_version"
implementation "io.ktor:ktor-server-conditional-headers:$ktor_version"

To help with migration, we’re providing folks not only mapping documentation but also a migration tool with IntelliJ IDEA which attempts to migrate your Ktor project automatically (please note that Kotlin Multiplatform Projects are currently not supported)

Kotlin 1.6.20 support and up to date documentation

For folks using the latest release of Kotlin, know that Ktor 2.0 is compatible with 1.6.20. We’ve also continued to work on the documentation for Ktor, bringing it up to speed with all the changes. Moving forward we’re working on revamping the API documentation also. 

For a complete list of everything in 2.0, check out the change log. And create your first Ktor 2.0 today! 

]]>
https://blog.jetbrains.com/zh-hans/ktor/2022/04/11/ktor-2-0-released/ https://blog.jetbrains.com/ko/ktor/2022/04/11/ktor-2-0-released/
Ktor Roadmap – What’s Next https://blog.jetbrains.com/ktor/2022/02/11/ktor-roadmap-what-s-next/ Fri, 11 Feb 2022 09:40:46 +0000 https://blog.jetbrains.com/?post_type=ktor&p=228027 We’re one month into 2022, and on the Ktor team we’re focusing on finalizing the little that is left from our side on 2.0 and waiting for Kotlin 1.6.20 to be released so as to release 2.0. At the same time, we’re planning the next things to be worked on. 

As some of you know, we had published our roadmap for 2020-2021 and while we didn’t manage to deliver on everything on it, we weren’t far off. However we also realized that we did in fact bite off more than we could chew. 

This led us to try and figure out whether the whole approach to a roadmap where you have a fixed timeline actually works. It definitely is an industry standard, and even at JetBrains many folks practice it, but at the same time it does have its own issues. In particular, it’s based on the idea that not only can we estimate things quite well, but it also doesn’t account for external factors or disruptions that could cause us to change course. 

Looking at the purpose of the roadmap, which is providing not only focus to the team on what we’re working on next, but also let all of you, our customers know what we’re working on, we decided to address these aspects as opposed to tie ourselves to a specific year.

As such, moving forward we will no longer be aligning our roadmap with natural years, but focusing on three different timeframes: short-term, mid-term, and long-term. The first of these is what our immediate focus is going to be on, and what we’ll be sharing publicly. As and when we complete things, we’ll move things from the mid-term to the short-term. 

Given that, let’s focus on what we have lined up next! 

Our short-term plans

The plan is distributed amongst different areas. In particular:

Infrastructure

From the infrastructure perspective, we still have a few areas that need addressing. We want to add YAML support for configuring applications, which is not only demanded by many of our users, but also already supported in the IDE. We also want to work on fixing some performance issues with Netty, as well as extract and implement a proper IO library with network support. 

Long standing issues

We have 150 issues that are long-standing (many of them imported from GitHub). While it is impossible to resolve all of them, we do intend to address them and fix/schedule accordingly. One issue that definitely will be worked on is Swagger support

Bootstrapping applications

We’ve made good efforts in making it easy to create new applications, but there are still many areas that need to be addressed. We are working on some cool things that will make starting with Ktor even easier for newcomers to the framework and to the JVM. We’ll be working on minimizing the amount of boilerplate code and set-up that needs to be done when it comes to working with databases. 

Deployment

We currently provide steps and guides on how to deploy Ktor applications, but we want to make it smoother by automating deployment configurations. 

Tooling Support

Over the past year we’ve managed to add quite a bit of support for IntelliJ IDEA. We want to build on this and provide even more functionality that is specific for Ktor, such as endpoint view, allowing you to get a better overview of the application architecture, helpers for creating plugins, and of course swagger support inline with our support for Swagger. 

Documentation

We’re still continuing to work on documentation. We now provide both the current release version as well as the next EAP version. In addition we have plans to review and update our API docs to make these more descriptive. 

Release Lifecycle

The release lifecycle will still remain the same. We still plan on releasing monthly patches, and committed to one major and several minor releases per year. 

The above is what we’ll be working on in the short term. We’ll keep you updated! 

]]>
https://blog.jetbrains.com/ko/ktor/2022/02/11/ktor-roadmap-what-s-next/
An update on our 2020-2021 roadmap https://blog.jetbrains.com/ktor/2021/08/10/an-update-on-our-2020-2021-roadmap/ Tue, 10 Aug 2021 11:30:00 +0000 https://blog.jetbrains.com/?post_type=ktor&p=170753 Exactly one year ago, we announced our plans for the upcoming year. Let’s look back and see how we’re doing.

Focus Areas

When we announced the roadmap, we focused on a few key areas that we wanted to improve. While on some of these, we’ve managed to deliver, on others we’re not there yet.

  • We’ve done a ton of work when it comes to Documentation. Our technical writer Andrey Aksenov deserves a lot of credit for mostly single-handedly not only rewriting many parts of the documentation, but also working on restructuring, and addressing new issues as they come in. Documentation however is an ongoing task, and we know we still have tons to do, especially documenting the API itself.
  • We’ve done quite a bit of work on simplifying the API, both for usage and extensibility. Most of these changes will be apparent in 2.x, as they imply breaking changes.
  • We’re currently working on improving testing to allow for better coverage of real-world scenarios.

For 2.0 we expect to have all the above ready, pending two main areas which still need addressing: client/server parity, and deployment. We aim to get these mostly done before the end of the year. Remember, if you want to try some of these things out, you can already under our EAP program.

Ending this roadmap in December does mean that we’ll be about 5 months behind schedule, but we believe all these areas are very important and the building blocks for what’s to come. As such we don’t have plans to change focus. The silver lining is that our next roadmap will align with the natural year, which believe it or not, makes things somewhat easier!

Commitment and Stability

We adopted semantic versioning, and by and large it seems we have not messed up much in this area, except the occasional bug that may have creeped in and broken some backwards compatibility. In regard to our commitment of frequent releases, we have been releasing at a minimum a patch fix every month, as well as two minor (1.5 and 1.6) releases since August 2020. We’re aiming to release 2.0 hopefully by October.

We also hired a full-time support engineer that continues to provide support via our official channel which is StackOverflow. By the way, either via comments or the survey, do let us know if you think a different channel is needed.

Tooling

In terms of tooling, we seem to be on course. We have completely rewritten the plugin from scratch, providing a smoother experience for setting up new projects. We have already started adding more functionality such as intentions, navigation, et al. to the plugin, and recently launched the new revamped project generator.

The plugin is now released with the new EAPs of IntelliJ IDEA and moving forward will be bundled with the product .

We’d also like to say a few words on our decision to provide support for IntelliJ IDEA Ultimate. When we announced the new plugin, we also highlighted that it would be available exclusively for IntelliJ IDEA Ultimate. While the vast majority of folks were fine with the decision, there were a few people that were somewhat upset by this move. We understand their opposition, but we want to reiterate the reasons for it; firstly, it is consistent with other frameworks we provide support for, such as Spring (Boot), Micronaut, et al. Secondly, we believe that OSS needs to be sustainable. Ktor will remain open source and free, but for us to be able to do this, we need to find a revenue model which works. For us, this is tooling.

Ktor Annual Survey and Job Openings

Last year we ran the first annual survey, which helped us greatly shape (and validate) our roadmap. It also highlighted the issues folks had and allowed us to concentrate on addressing them. Yesterday we launched our second Ktor Annual Survey. We’d really appreciate it if you could take 5-10 minutes to fill it in.

Lastly, if you like Ktor and want to help, we have a few positions open. We’d love to have you join the team!

]]>
Ktor 1.6.0 Released https://blog.jetbrains.com/ktor/2021/05/28/ktor-1-6-0-released/ Fri, 28 May 2021 14:00:40 +0000 https://blog.jetbrains.com/?post_type=ktor&p=146456 We’re happy to announce the availability of Ktor 1.6.0. This minor release brings with it some new features, deprecations, and of course more bug fixes!

Features

This release brings a bunch of new functionality to the client, inline with our goals to have client and server parity.

Client Progress Support

You can now monitor the progress of bytes sent and received in the client, allowing you to for instance provide progress bars in your applications. This was a long-standing issue which has finally been resolved.

val response: HttpResponse = client.post("http://localhost:8080/post") {
body = content
onUpload { bytesSendTotal: Long, contentLength: Long -> updateUICode() }
}

Client Bearer authentication support

The client now supports Bearer authentication, another long-standing issue that has been resolved!

val client = HttpClient() {
    install(Auth) {
        bearer {
            loadTokens {
                BearerTokens(accessToken = "hello", refreshToken = "world")
            }

            refreshTokens { response: HttpResponse ->
                BearerTokens(accessToken = "hello", refreshToken = "world")
            }
        }
    }
}

Ignore trailing slashes

We added a new plugin (new name we’re giving to Features) which tells Ktor to ignore trailing slashes during route matching. To make use of it, simply install the plugin.

install(IgnoreTrailingSlash)

Note that this is meant to be installed a single time and would apply to any `routing` block defined in the application.

Other features and updates

In addition to the above, routing now supports PATCH and PUT generic methods. The TrailingSlashRouteSelector property has now been made public (as was originally intended), and we’ve also added the ability to disable URL encoding on the client.

In addition to the outlined features and numerous bug fixes and documentation improvements, this version

As always, the release is available on Maven Central, and you can also find/install dependencies using Package Search.

The Ktor Team

]]>
Ktor Plugin Update – Navigation, Refactoring, and more! https://blog.jetbrains.com/ktor/2021/04/07/ktor-plugin-update-navigation-refactoring-and-more/ Wed, 07 Apr 2021 11:07:54 +0000 https://blog.jetbrains.com/?post_type=ktor&p=132583 As a tooling company, we do realise the importance of providing proper support for the languages and frameworks you use.

In the case of Ktor, we started this journey by rewriting support for IntelliJ IDEA Ultimate completely from scratch, and the first step was a new and simplified project wizard, which has already been announced.

With the 1.5.3 update, we’re improving the options in the wizard, as well as bringing new functionality!

New Project Enhancements

The Project Wizard comes with two new options:

Storing configuration

Via the Configuration in dropdown, you can define whether you want the generated project to store the server configuration as code, i.e. using the embeddedServer option, or external HOCON files.

Sample Code

By default, when adding Features (soon to be renamed to Plugins), the wizard generates some sample code for you to get you started. This is very useful for beginner, but may not be of value to more experienced users. We’ve now made this optional via the Add sample code checkbox.

Wizard

In both cases, Ktor will also generate the corresponding Run Configuration entries.

Development Enhancements

One of our goals with Ktor support in IntelliJ IDEA is to improve the overall development experience. This release
brings a bunch of new functionality in this area.

Navigation

You can now navigate to actual routes across a project. For instance, if you have a Ktor server with a specific route, and you’re referencing it from a client, you can navigate to it using the standard IntelliJ IDEA shortcuts/actions (Ctrl/Cmd+Click or Ctrl/Cmd+B), or with
Globe icon next to the URL string

Globe Icon

Much the same way, from a specific route definition, you can navigate to the usages

Find Usages

Finding routes with Search Everywhere

If you want to find a specific route in your application, you can do so using Search Everywhere (Double Shift)

Search Everywhere

Endpoint View

To see a list of all endpoints that the current module offers, you can use the Show enpoints of module

Show Endpoints

which then displays a list of endpoints in the Endpoints tool window

Endpoints tool window

From this window, you can test the call as well as open it in the HTTP editor. It will automatically detect
parameters and prompt you for these

Endpoint Execute

You can of course generate a test client request from a specific route using the Open in HTTP client option from the globe icon.

Generate Http Client

Rename Refactoring

Ktor allows you to define routes in one of two ways:

  • Using Strings
  • Using Locations (a feature that is currently being reworked)

One drawback of using strings of course is, that when it comes to renaming, this can be a bit cumbersome. Not anymore!

Much like you can now navigate to URLs and find usages, you can also perform a rename refactor, knowing that any reference to them will be renamed too. This also includes parameter names.

Rename Refactor

The IDE allows you to define the scope you want the refactoring to be applied to in case you want to limit this.

Completion

Last but certainly not least, there is also support for completion.

Completion

This is just a taster of the many features we have planned, to improve the development, testing, and deployment experience with Ktor. We’d love for you to try the plugin and let us know if you have any feedback.

]]>
Say Hello to Ktor Early Access Program and New Plugin https://blog.jetbrains.com/ktor/2021/02/03/say-hello-to-ktor-early-access-program-and-new-plugin/ Wed, 03 Feb 2021 11:43:07 +0000 https://blog.jetbrains.com/?post_type=ktor&p=113007 We’re very excited to announce the Ktor Early Access Program, where you can get access (thus the name) to things we’re working on that won’t be available in the currently released version.

Often times we’d like to introduce new functionality or APIs that may not be backwards compatible, and get these out to you as soon as they’re ready for feedback. That’s what our EAP program is about. It’s important to understand that while these are not marked as releases, they do go through the same (if not more) tests and checks that our releases go through.

We do encourage folks to try EAPs builds, but also please understand that they are not official releases.

When and where

New builds and artifacts for EAPs will be released on a nightly basis. We’ll be building on any *-eap branches that we have as well as the default main branch. These will be made available on our public Space Repository.

We’re adding Space support to Package Search, so soon you’ll be able to search and add them directly from inside the IDE. For now, check out the EAP page for instructions on how to add the necessary dependencies.

Important – EAP artifacts will not be kept indefinitely. We’ll be cleaning them up on a frequent basis.

IntelliJ IDEA Ultimate Plugin

One other thing we’ve been working on is the new plugin for Ktor! This is a complete rewrite for Ktor and comes with a new wizard that makes it simpler to create Ktor applications.

A two-step process guides you through what’s needed to get your Ktor Server application. From selecting the basics of the application such as the name, engine to use, etc.

Wizard Step 1 - Select Project entries

to choosing the exact features you want to add.

Wizard Step 2 - Add Features

At any point you can also view and remove selected features

Wizard Results

The plugin currently only provides new project functionality, but it also constitutes the basis for all the features we’ll be adding for Ktor to IntelliJ IDEA Ultimate, including but not limited to inspections, navigation, and intentions specifically targeted to Ktor applications.

You can download the plugin either from within IntelliJ IDEA Ultimate or from the JetBrains Marketplace. Also check out the new tutorial on how to work with it.

A word on IntelliJ IDEA support

You may be wondering why we’re only going to be providing Ktor support for IntelliJ IDEA Ultimate. At JetBrains we make tools, amongst which are IDEs, languages, and frameworks (such as Ktor). Our goal is to provide the best experience for developers and to continue to be able to do this in a way that is sustainable as a business. In the case of Ktor, the framework itself is and will always remain free and Open Source, and licensed under Apache 2. However, tooling will only be available as part of IntelliJ IDEA Ultimate, which is inline with our support for other frameworks. The existing plugin will remain open source and available, but will no longer be maintained past 1.5.2

For folks that want to create new projects, the Ktor Generator which is also in the process of being revamped, will be available. While we may add additional features to it in the future, generating projects will remain always free.

We do hope you try out the new plugin, as well as our EAPs and provide us with feedback to continue to improve Ktor!

]]>
Ktor 1.5.0 Released https://blog.jetbrains.com/ktor/2020/12/22/ktor-1-5-0-released/ Tue, 22 Dec 2020 08:30:50 +0000 https://blog.jetbrains.com/?post_type=ktor&p=105838 We’re happy to announce the release of Ktor 1.5.0, which comes with new features, bug fixes, and new docs!

Features

1.5.0 is the third and final release for this year, inline with our promise to have three major or minor releases a year, and a minimum of one patch release a month. We’re happy to say that so far we’ve managed to more or less keep this promise, albeit with an ocassional delay at times.

In this minor update we have a series of new features including:

New Development Mode

Ktor provides a series of features targeted at development, such as for instance auto-reload as well as extended debug information. While both of these are useful during development, they can slow things down in production mode. With 1.5.0 we’re introducing a new development mode which enables this functionality with a simple configuration or flag. It also makes it easier to switch settings for production.

The feature can be activated using development=true in application.conf.

This is a breaking change (backwards compatible) as auto-reload is now only enabled in this new mode.

Support for Java HTTP Client

Java 11 introduces an HTTP Client based on reactive streams. Ktor client
now supports this when targeting the JVM.

In order to use it, simply pass in as parameter to HttpClient the value Java.

    HttpClient(Java)

It’s a given that you do need Java 11 for this!

Support for sending cookies via HttpRequestBuilder

If using the HttpRequestBuilder, you now have a new method named cookies which allows you to send cookies easily

 cookies {
    append("my_cookie", value = "My cookie Value")
}

Support for precompressed files

A lot of times you want to send files that are already compressed, and avoid Ktor trying to compress further the contents. With the preCompressed feature
you can now do that easily:

static {
    preCompressed {
        files(temp.parentFile)
    }
}

Thank you to our community contributor guicamest for their contribution.

Support for custom headers in CORS

We now have support for allowing custom headers in CORS requests. While it’s not generally advisable to allow any header in a request, you can specify with Ktor certain custom headers that follow a specific pattern:

 application.install(CORS) {
    anyHost()
    allowHeadersPrefixed("custom-")
}

Thanks to Joze for this contribution.

Experimental WebSocket and Deflate Extensions

We’ve introduced support for WebSocket and deflate extensions. This provides an implementation to RFC-7692.

To use it, install the feature

install(WebSockets) {
    extensions { 
        install(WebSocketDeflateExtension) { 

            // Deflate option
            compressionLevel = Deflater.DEFAULT_COMPRESSION
        }
    }
}

and simply reference it with one of the two new methods: extension and extensionOrNull

webSocket("/echo") {
    val myExtension = extension(MyWebSocketException) 
    // will throw if `MyWebSocketException` is not negotiated

    val myExtension = extensionOrNull(MyWebSocketException) ?: close() 
    // will close the session if `MyWebSocketException` is not negotiated
}

It’s important to note that this is an experimental API and we’d love to get some feedback on it

Support for sealed and nested classes in Server Sessions

You can now have sealed/nested classes in your server session object


data class MySession(val id: String, kind: UserInfo) 

sealed class UserInfo() {
    data class Admin(val drafts: List<String>) : UserInfo()
    data class Reader(val ids: List<String>) : UserInfo()
}

install(Sessions) {
    cookie<MySession>("SESSION") 
}

OkHttp WebSocket creation override

You can now provide an OkHttp WebSocket.Factory which will be taken into account when creating websockets, giving you more flexibility when working with OkHttp. Thank you to Chris for their contribution.

Proper exception handling

Ktor now handles unexpected exceptions correctly. If an exception occurs in the pipeiline, it is propagated to the host and returned as a 500 Internal Server Error with the actual exception object. This allos for better handling on exceptions by the application itself, and no longer requires that you have status pages configured for that particular status code.

In addition to the features outlined above, 1.5.0 also comes with other features and bug fixes

New Documentation

One of the items on our roadmap for 2020-2021 was to improve the onboarding experience which of course includes better documentation. In particular we’re rewriting much of the content and structuring it better. We’ve now completely roughly half of the contents and it’s available for you to consume and give feedback on. Please note that there are still legacy entries and as we push new
contents, some of these will be removed (and redirects put in place).

Acknowledgements

In addition to the contributions outlined above, we’d like to thank all contributors to Ktor, be it in the form of code contributions, as well as feedback and reporting issues.

Getting the bits

As usual, you can get the bits on Maven Central or use Package Search to search/manage Ktor dependencies directly in your project.

We hope you enjoy this release, and see you in 2021 with much more.

Happy Holidays!

]]>
Ktor Design Process https://blog.jetbrains.com/ktor/2020/09/24/ktor-design-process/ Thu, 24 Sep 2020 12:28:00 +0000 https://blog.jetbrains.com/?post_type=ktor&p=78559 Design in the open

Ktor was created as an Open Source project and continues to remain one. During its development, feedback from the community has and continues to be fundamental, and very much appreciated.

We’d like to take this to the next step by having all our design decisions in the open. The process will work as follows:

Step 1

We create a ticket on YouTrack of type Design, and in it we’ll lay out:

Description of the issue

What it is that we’re addressing. Is it a new API? Is it improvements on existing APIs? Is it internal architecture?

Current State

If applicable, we outline the current state.

Proposed Solution

Proposed solution, highlighting

  • If the solution has API changes – which these will be.
  • Pros and Cons

Agreed Solution

Once the discussion has taken place, and the agreed solution has been reached, it will be provided it in this segment.

Step 2

The ticket will remain open for 10 working days during which team the core Ktor team and members of the community can share their feedback.

Step 3

After the 10 days have passed, a design decision should be made. Once done, the Agreed Solution section should be updated.

Design meetings

While it may be the case that the Core team will hold a design meeting, we will try as much as possible to keep all discussions on the ticket, for full transparency.
If we do have a meeting, we’ll update the ticket with the corresponding outcome.

Being notified of Design questions

If you’d like to be notified on Design tickets, you can configure YouTrack to receive notifications for this type of ticket. Additionally we’ll aim to raise these tickets in the Ktor Channel on Kotlin Slack.

This won’t be Design by Committee

We generally do not believe in design by a committee, nor do we believe in Ivory Towers, where we make design decisions without input from our users.

The goal of this process is to be transparent, get feedback and make sure that we cover scenarios we may not have thought of. However, please understand that the ultimate decision will always be that of the core team. Having said that, any decision we make, we need to be able to justify to you, our users.

Finally, as a user, you’re free to continue to make suggestions that can be filed either as a bug or a feature. If needed, the core team will create the corresponding design ticket.

]]>