Migrating 0.9.2 → 0.9.3

Estimated reading time: 5 minutes

Ktor 0.9.3 fixes some bugs, bumps some versions, improves the overall performance of the server, and introduces new APIs and changes for some of them.

This version is expected to be mostly source-code compatible with 0.9.2 except for advanced use-cases related with kotlinx.coroutines and Ktor Raw sockets.

https://github.com/ktorio/ktor/compare/0.9.2...0.9.3

Changelog

0.9.3

Published 26 Jun 2018

  • Improved WebSocket API
  • Websocket header Sec-WebSocket-Key is now optional
  • Fixed client cookies rendering to avoid x-enc
  • Fixed plain text client reader (#392)
  • Added EC support in CIO TLS (#394: ECDHE_RSA_AES256_SHA384, ECDHE_RSA_AES128_SHA256)
  • Fix client certificate validation
  • Introduced optional authentication
  • Added ApplicationCall as receiver for auth validate functions
  • Introduced call.respondBytes (#395)
  • Improved JWT support: multiple schemes, nullable issuer
  • Conversion service enum type diagnostics improved (#403)
  • Avoided using apos entity in HTML escaping as IE doesn’t support it (#400)
  • Converter support for java big numbers
  • Ability to add auth methods to existing feature on the fly
  • Improved auth header scheme and contents validation (#415)
  • Default charset for BasicAuth is now UTF-8 (#420)
  • Added ByteArrayContent.contentLength (#421)
  • Fixed headersOf case insensitive issue (#426)
  • Client deserialization improved by using type token
  • Ability to disable client default transformers
  • Explicit Accept header in client request
  • Turn on masking in client websockets (#423)
  • Fixed inverted PartialContent.Configuration.maxRangeCount check (#440)
  • Fixed uncaught UnsupportedMediaTypeException from receiveOrNull() (#442)
  • Fix multipart boundary header parsing
  • Upgraded jwks/jwt, applied RSA256 by default if unspecified (#434, #435)
  • Upgrade kotlinx.coroutines to 0.23.3
  • Upgrade Jetty version to 9.4.11.v20180605
  • Add client-mock-engine for testing purpose
  • HttpClient allows to use default available engine if not provided one
  • Upgrade kotlin to 1.2.50
  • Move ktor-samples to a separate repository (#340). https://github.com/ktorio/ktor-samples
  • Added client redirect feature *

Client

WebSocket improvements

Now webSocketSession and webSocketRawSession return DefaultClientWebSocketSession and webSocket, ws and wss methods also receives a DefaultClientWebSocketSession and other methods return a ClientWebSocketSession.

This prevents having to cast to access some properties from the client session:

var DefaultWebSocketSession.pingInterval: Duration?
var DefaultWebSocketSession.timeout: Duration
val DefaultWebSocketSession.closeReason: Deferred<CloseReason?>
var DefaultClientWebSocketSession.masking: Boolean

HttpClient MockEngine

We had a MockEngine available internally for our tests for creating an HttpClient that was able to respond from our code programmatically without actually performing any request.

We have now exposed it in the io.ktor:ktor-client-mock artifact.

For example:

val mockEngine = MockEngine { call -> // suspend HttpRequest.(call: HttpClientCall) -> MockHttpResponse
    assertEquals("*/*", headers[HttpHeaders.Accept])

    MockHttpResponse(call, HttpStatusCode.OK, writer(ioCoroutineDispatcher) { channel.writeStringUtf8("HELLO") }.channel, headersOf(
        "X-Custom-Header" to listOf("value")
    ))
}

val client = HttpClient(mockEngine)

Inside the MockEngine block, you can assert things from the request, or decide how to generate a response based on the request.

HttpClient default Engine

Now you can instantiate a HttpClient by just HttpClient() without providing an engine. In that case it will use a ServiceLoader to find a suitable implementation based on the artifacts you have included.

HttpClient HttpRedirect feature

Now you can use the new client HttpRedirect feature to follow HTTP Location-based redirections. Read the documentation for more information.

HttpClient bug fixes

Now the HttpClient sends cookies in a standard way with one single header separating cookies by ;.

Reading an empty body as String with an Httpclient (HttpClient.get<String>) was causing a No transformation found: class io.ktor.client.engine.apache.ApacheHttpResponse -> class kotlin.String exception.

HttpClientEngine changes

HttpClientEngine now has a config field. So you will have to provide it in the case you have a custom engine.

HttpClient changes

Now the HttpClient sends an Accept header. If you have a test checking all the headers, you will need to update them.

Sockets

TLS improvements

Ktor implements secure sockets using CIO, and the TLS available before 0.9.3 missed some cypher suites and encryption methods. We have updated it to support more required stuff.

Some errors you could encounter that now might be fixed:

  • Exception in thread "io-thread-1" io.ktor.network.tls.TLSException: Received alert during handshake. Level: FATAL, code: HandshakeFailure
  • Exception in thread "io-thread-2" io.ktor.network.tls.TLSException: Unsupported TLS handshake type CertificateRequest

aSocket breaking change

aSocket now requires a SelectorManager to be provided.

For example:

aSocket(ActorSelectorManager(ioCoroutineDispatcher))

Of course, you can reuse the SelectorManager:

val mySocketSelector = ActorSelectorManager(ioCoroutineDispatcher)
val socket = aSocket(mySocketSelector).tcp()

Server

WebSocket improvements

Before 0.9.3, when a WS request was made without the Sec-WebSocket-Key header, an IllegalArgumentException was thrown. Now it is optional.

Optional Authentication

Now it is possible to define a set of routes where you can provide authentication, but it is optional:

authenticate("method", optional = true) {
    // routes
}
 

The authenticate behaviour:

  • No authentication provided:
    • optional=false: challenge is performed
    • optional=true: route handler is executed with principal=null
  • Wrong credentials: Unauthorized
  • Valid credentials: route handler is executed with the principal generated from the authentication method

Missing call.respondBytes

Before 0.9.3 we had call.respondText but missed call.respondBytes. We have solved this.

Version bumps

Ktor now uses Kotlin 1.2.50 and kotlinx.coroutines 0.23.3.

kotlinx.coroutines has some breaking changes for advanced use-cases.

generateCertificate

We have moved the generateCertificate function for generating self-signed certificates to the ktor-network-tls artifact: compile "io.ktor:ktor-network-tls:$ktor_version"

New ktor-samples repository

Before 0.9.3, we had several sample projects integrated directly in the ktor repository. They have grown, and we have moved them to their own repository: https://github.com/ktorio/ktor-samples