© fatmawati achmad zaenuri/Shutterstock.com
Warum es sich lohnt, das Web-Framework auszuprobieren

Wer Kotlin mag, wird Ktor lieben


Mit der steigenden Beliebtheit von Kotlin kommt auch der Wunsch nach einem Web-Framework auf, das perfekt zu Kotlin passt und dessen Features sinnvoll sind. Ein Web-Framework wie Ktor. Achtung: Dieser Artikel bietet keine Einführung in Kotlin. Das Meiste sollte aber auch ohne fundiertes Kotlin-Know-how verständlich sein.

Ktor ist wohl das bekannteste in Kotlin geschriebene Framework für Webserver und -clients. Eigentlich kein Wunder, da es vom Kotlin-Schöpfer JetBrains selbst stammt. Nach über sechs Jahren Entwicklung [1] macht das Framework einen recht ausgereiften Eindruck – und wenn man nicht gerade ein spezielles Feature vermisst, sollte man es auf jeden Fall für neuen Projekte in Betracht ziehen.

Neben der Verwendung von Kotlin-nativen Features wie Koroutinen zeichnet sich Ktor dadurch aus, dass es sehr leichtgewichtig ist. In Kombination mit der auf Erweiterungen ausgelegten Architektur ist die Entwicklung mit Ktor sehr empfehlenswert.

Server

Den größten Teil von Ktor bildet das API zum Erstellen von HTTP APIs. Ich möchte zeigen, wie man mit Ktor einen simplen HTTP-Server erstellt und mit welchen Konzepten man diesen erweitern kann.

Hello World

Ktor macht intensiven Gebrauch vom Typesafe-Builder-Pattern (aka Kotlin DSL). So sieht ein „Hello World“ mit Ktor etwa aus wie in Listing 1.

Listing 1

fun main() { embeddedServer(Netty, port = 8080) { routing { get ("/") { call.respondText("Hello, world!") } } }.start(wait = true) }

embeddedServer akzeptiert als letzten Parameter eine Funktion, die im Application-Kontext ausgeführt und dazu verwendet wird, den Ktor-Server zu konfigurieren. Diese Funktion bildet den Einstiegspunkt in die Konfiguration des Servers. In der Regel wird von hier aus jeglicher Ktor-bezogene Code aufgerufen.

Features

Die wohl wichtigste Funktion im Application-Kontext ist install(…). Mit install(…) können Ktor-Features aktiviert und konfiguriert werden.

Will man beispielsweise CORS-Support (Cross-Origin Resource Sharing) aktivieren, sieht das wie in Listing 2 aus.

Listing 2

fun main() { embeddedServer(Netty, port = 8080) { install(CORS) routing { get ("/") { call.respondText("Hello from another origin!") } } }.start(wait = true) }

Auch in Listing 1 wird bereits – wenn auch etwas versteckt – ein Feature verwendet. Die Implementation von routing sieht hier nämlich so aus [2], wie in Listing 3 gezeigt.

Listing 3

@ContextDsl fun Application.routing(configuration: Routing.() -> Unit): Routing = featureOrNull(Routing)?.apply(configuration) ?: install(Routing, configuration)

routing(…) prüft demnach, ob das Routingfeature bereits installiert wurde. Wenn das der Fall ist, führt es die Konfigurationsfunktion des Features im Kontext des existierenden Features aus. Falls nicht, ruft es install(Routing, configuration) auf, aktiviert also das Feature und konfiguriert es dann initial mit der gegebenen Konfiguration. Dieser Mechanismus ermöglicht es, routing mehrmals aufzurufen, um die Implementation verschiedener Routen aufteilen und die Anwendung besser strukturieren zu können. Wichtig ist: Features dürfen nur einmal „installiert“ werden.

Neben dem Routingfeature gibt es zahlreiche weitere Features, darunter die in Tabelle 1 gezeigten.

Feature

Funktionalität

Authentication

erlaubt es, Authentifizierungsmethoden für Routen zu definieren

CallLogging

Logging von Requests

ContentNegotiation

transformiert eingehende Daten basierend auf ihrem Content-Type

Compression

aktiviert Kompression für die Response

CORS

setzt CORS-Header in der Response

HSTS

setzt HSTS-Header in der Response

Locations

ergänzt Routing um typisierte Routen

Sessions

ermöglicht Sessions via Cookie oder Header (inkl. Signierung oder Verschlüsselung)

Tabelle 1: Weitere Features

Wem die mitgelieferten Features nicht genügen, der kann weitere Features aus Bibliotheken installieren oder auch eigene Features implementieren. Oft bedarf es aber keiner vollwertigen Features, sondern es reicht, das zugrunde liegende Konzept der Interceptors zu verwenden.

Interceptors und Pipelines

Um Interceptors zu verstehen, müssen wir einen kurzen Blick darauf werfen, wie Ktor intern Requests behandelt.

Ktor nutzt zur Bearbeitung von Requests drei wichtige ...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang