Part 6 · 1 chapters · ~8 min
Ktor End to End
A Ktor service from scratch: engines, plugins (content negotiation with kotlinx.serialization, authentication, status pages, call logging), the routing DSL, request validation, dependency injection with Koin or by hand, database access with Exposed and HikariCP, idempotency keys, OpenAPI, and packaging.
7
A transfers endpoint in Ktor
code
fun Application.module() {
install(ContentNegotiation) { json() }
install(StatusPages) { exception<IllegalArgumentException> { call, e -> call.respond(HttpStatusCode.UnprocessableEntity, mapOf("error" to e.message)) } }
install(Authentication) { bearer("api") { authenticate { creds -> apiKeys.principal(creds.token) } } }
routing {
authenticate("api") {
post("/v1/transfers") {
val key = call.request.header("Idempotency-Key") ?: return@post call.respond(HttpStatusCode.BadRequest)
val body = call.receive<CreateTransferRequest>()
when (val r = transfers.create(body, key)) {
is TransferResult.Ok -> call.respond(HttpStatusCode.Created, r.transfer.toDto())
is TransferResult.InsufficientFunds -> call.respond(HttpStatusCode.UnprocessableEntity, mapOf("error" to "insufficient_funds"))
TransferResult.LimitExceeded -> call.respond(HttpStatusCode.UnprocessableEntity, mapOf("error" to "limit_exceeded"))
}
}
}
}
}
fun main() = embeddedServer(Netty, port = 8080, module = Application::module).start(wait = true)KTOR END TO END
a coroutine-native web framework from JetBrains
swipe the figure sideways, or tap expand for full screen
1/4
engine and plugins
Ktor runs on an engine (Netty, CIO) and is assembled from plugins: you install only what you use, keeping services small.
pick your pluginssmall by default