kotlinintermediate

Ktor Server Routing and Middleware

Build HTTP APIs with Ktor: routing, content negotiation, authentication, and middleware plugins.

kotlin
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.application.*
import io.ktor.server.routing.*
import io.ktor.server.response.*
import io.ktor.server.request.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.plugins.contentnegotiation.*
import kotlinx.serialization.Serializable

@Serializable
data class User(val id: Int, val name: String, val email: String)

@Serializable
data class CreateUserRequest(val name: String, val email: String)

@Serializable
data class ApiResponse<T>(val data: T? = null, val error: String? = null)

fun Application.configureRouting() {
    install(ContentNegotiation) { json() }

    val users = mutableListOf(
        User(1, "Alice", "alice@test.com"),
        User(2, "Bob", "bob@test.com")
    )
    var nextId = 3

    routing {
        route("/api/users") {
            get {
                call.respond(ApiResponse(data = users.toList()))
            }

            get("/{id}") {
                val id = call.parameters["id"]?.toIntOrNull()
                    ?: return@get call.respond(HttpStatusCode.BadRequest,
                        ApiResponse<Nothing>(error = "Invalid ID"))
                val user = users.find { it.id == id }
                    ?: return@get call.respond(HttpStatusCode.NotFound,
                        ApiResponse<Nothing>(error = "User not found"))
                call.respond(ApiResponse(data = user))
            }

            post {
                val request = call.receive<CreateUserRequest>()
                val user = User(nextId++, request.name, request.email)
                users.add(user)
                call.respond(HttpStatusCode.Created, ApiResponse(data = user))
            }

            delete("/{id}") {
                val id = call.parameters["id"]?.toIntOrNull()
                    ?: return@delete call.respond(HttpStatusCode.BadRequest,
                        ApiResponse<Nothing>(error = "Invalid ID"))
                if (users.removeIf { it.id == id })
                    call.respond(HttpStatusCode.NoContent)
                else call.respond(HttpStatusCode.NotFound,
                    ApiResponse<Nothing>(error = "Not found"))
            }
        }

        get("/health") { call.respond(mapOf("status" to "UP")) }
    }
}

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

Sponsored

Railway

Use Cases

  • Building REST APIs with Kotlin-native framework
  • Lightweight microservice development
  • API prototyping with Ktor DSL

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.