Ktor server core module for iOS ARM64 target providing essential server-side functionality for building asynchronous web applications and microservices in Kotlin Multiplatform
—
Core application structure, configuration, lifecycle management, and the comprehensive plugin system. This includes the main Application class, pipeline processing, environment setup, and extensible plugin architecture.
The main application class representing a configured and running web application.
/**
* Represents a Ktor application instance
*/
class Application internal constructor(
environment: ApplicationEnvironment,
developmentMode: Boolean,
var rootPath: String,
val monitor: Events,
val parentCoroutineContext: CoroutineContext,
private val engineProvider: () -> ApplicationEngine
) : ApplicationCallPipeline(developmentMode, environment), CoroutineScope {
/** The application engine running this application */
val engine: ApplicationEngine
/** Dispose the application and wait for completion */
suspend fun disposeAndJoin()
}
/** Extension property to get application logger */
val Application.log: LoggerCore interfaces for handling individual HTTP requests through pipeline processing.
/**
* Represents a single act of communication between client and server
*/
interface ApplicationCall : CoroutineScope {
/** Attributes associated with this call */
val attributes: Attributes
/** The incoming request */
val request: ApplicationRequest
/** The outgoing response */
val response: ApplicationResponse
/** The application handling this call */
val application: Application
/** Parameters associated with this call */
val parameters: Parameters
/** Receive request body with type information */
suspend fun <T> receiveNullable(typeInfo: TypeInfo): T?
/** Send response with type information */
suspend fun respond(message: Any?, typeInfo: TypeInfo?)
}
/**
* Extended ApplicationCall interface with pipeline-specific functionality
*/
interface PipelineCall : ApplicationCall
/**
* Pipeline configuration for executing PipelineCall instances
*/
open class ApplicationCallPipeline : Pipeline<Unit, PipelineCall> {
/** Pipeline for receiving request content */
val receivePipeline: ApplicationReceivePipeline
/** Pipeline for sending response content */
val sendPipeline: ApplicationSendPipeline
companion object {
/** Phase for call setup and preparation */
val Setup: PipelinePhase
/** Phase for monitoring and logging */
val Monitoring: PipelinePhase
/** Phase for plugin processing */
val Plugins: PipelinePhase
/** Phase for actual call handling */
val Call: PipelinePhase
/** Phase for fallback handling */
val Fallback: PipelinePhase
}
}Configuration classes for server setup and lifecycle management.
/**
* Core configuration for a running server
*/
class ServerConfig {
/** Application environment configuration */
val environment: ApplicationEnvironment
/** Root path for the application */
val rootPath: String
/** Whether development mode is enabled */
val developmentMode: Boolean
/** Parent coroutine context */
val parentCoroutineContext: CoroutineContext
}
/**
* Builder for ServerConfig instances
*/
class ServerConfigBuilder {
/** Configure application modules */
fun module(body: suspend Application.() -> Unit)
/** Paths to watch for auto-reload in development */
var watchPaths: List<String>
/** Root path for the application */
var rootPath: String
/** Enable development mode features */
var developmentMode: Boolean
}
/**
* Create a ServerConfig instance
*/
fun serverConfig(block: ServerConfigBuilder.() -> Unit): ServerConfigEnvironment interface representing the context in which an Application runs.
/**
* Represents environment in which Application runs
*/
interface ApplicationEnvironment {
/** Logger instance for the application */
val log: Logger
/** Application configuration */
val config: ApplicationConfig
}
/**
* Common implementation of ApplicationEnvironment
*/
expect class CommonApplicationEnvironment : ApplicationEnvironmentComprehensive plugin architecture for extending Ktor functionality.
/**
* Base interface for all plugins
*/
interface Plugin<TPipeline, TConfiguration, TPlugin> {
/** Unique key identifying this plugin */
val key: AttributeKey<TPlugin>
/** Install the plugin into a pipeline */
fun install(pipeline: TPipeline, configure: TConfiguration.() -> Unit = {}): TPlugin
}
/**
* Plugin that can be installed into Application
*/
interface ApplicationPlugin<TConfiguration> : BaseApplicationPlugin<Application, TConfiguration, PluginInstance>
/**
* Plugin that can be installed into RoutingNode
*/
interface RouteScopedPlugin<TConfiguration> : Plugin<RoutingNode, TConfiguration, PluginInstance>
/**
* Instance of a plugin installed to an application
*/
class PluginInstance/**
* Utility class to build ApplicationPlugin instances
*/
abstract class PluginBuilder<PluginConfig> {
/** Register handler for call processing */
fun onCall(block: suspend OnCallContext<PluginConfig>.(call: PipelineCall) -> Unit)
/** Register handler for call receive events */
fun onCallReceive(block: suspend OnCallReceiveContext<PluginConfig>.(call: PipelineCall, body: Any) -> Unit)
/** Register handler for call respond events */
fun onCallRespond(block: suspend OnCallRespondContext<PluginConfig>.(call: PipelineCall, body: Any) -> Unit)
/** Register hook handler */
fun <HookHandler> on(hook: Hook<HookHandler>, handler: HookHandler)
}
/**
* Builder for RouteScopedPlugin instances
*/
abstract class RouteScopedPluginBuilder<PluginConfig> : PluginBuilder<PluginConfig>() {
/** The route this plugin is scoped to */
val route: RoutingNode?
}/**
* Create an ApplicationPlugin with no configuration
*/
fun createApplicationPlugin(
name: String,
body: PluginBuilder<Unit>.() -> Unit
): ApplicationPlugin<Unit>
/**
* Create an ApplicationPlugin with custom configuration
*/
fun <PluginConfigT> createApplicationPlugin(
name: String,
createConfiguration: () -> PluginConfigT,
body: PluginBuilder<PluginConfigT>.() -> Unit
): ApplicationPlugin<PluginConfigT>
/**
* Create a RouteScopedPlugin with no configuration
*/
fun createRouteScopedPlugin(
name: String,
body: RouteScopedPluginBuilder<Unit>.() -> Unit
): RouteScopedPlugin<Unit>
/**
* Create a RouteScopedPlugin with custom configuration
*/
fun <PluginConfigT> createRouteScopedPlugin(
name: String,
createConfiguration: () -> PluginConfigT,
body: RouteScopedPluginBuilder<PluginConfigT>.() -> Unit
): RouteScopedPlugin<PluginConfigT>/**
* Install a plugin into an application
*/
fun <TConfiguration> Application.install(
plugin: ApplicationPlugin<TConfiguration>,
configure: TConfiguration.() -> Unit = {}
): PluginInstance
/**
* Install a plugin into a route
*/
fun <TConfiguration> Route.install(
plugin: RouteScopedPlugin<TConfiguration>,
configure: TConfiguration.() -> Unit = {}
): PluginInstance
/**
* Get a plugin instance, throws if not installed
*/
fun <TConfiguration> Application.plugin(plugin: ApplicationPlugin<TConfiguration>): PluginInstance
/**
* Get a plugin instance or null if not installed
*/
fun <TConfiguration> Application.pluginOrNull(plugin: ApplicationPlugin<TConfiguration>): PluginInstance?Event-driven hooks for plugin integration and lifecycle management.
/**
* Hook that can be registered in PluginBuilder
*/
interface Hook<HookHandler> {
/** Install the hook into a pipeline */
fun install(pipeline: ApplicationCallPipeline, handler: HookHandler)
}
/**
* Hook invoked as first step in processing a call
*/
object CallSetup : Hook<suspend (PipelineCall) -> Unit>
/**
* Hook invoked when call fails with exception
*/
object CallFailed : Hook<suspend (PipelineCall, Throwable) -> Unit>
/**
* Hook for when response body is ready to be sent
*/
object ResponseBodyReadyForSend : Hook<suspend (PipelineCall) -> Unit>
/**
* Hook for when response was successfully sent
*/
object ResponseSent : Hook<suspend (PipelineCall) -> Unit>
/**
* Shortcut hook for Application.monitor subscription
*/
class MonitoringEvent<T>(val definition: EventDefinition<T>) : Hook<suspend (T) -> Unit>Application module management and startup configuration.
/**
* Application startup mode for modules
*/
enum class ApplicationStartupMode {
SEQUENTIAL,
CONCURRENT
}Useful extension properties for Application and ApplicationConfig.
/** Get application logger */
val Application.log: Logger
/** Get host configuration from ApplicationConfig */
val ApplicationConfig.host: String
/** Get port configuration from ApplicationConfig */
val ApplicationConfig.port: IntExceptions related to plugin management and application lifecycle.
/**
* Thrown when plugin with same key is already installed
*/
class DuplicatePluginException(message: String) : Exception(message)
/**
* Thrown when accessing plugin that is not installed
*/
class MissingApplicationPluginException(key: AttributeKey<*>) : IllegalStateException()import io.ktor.server.application.*
import io.ktor.server.engine.*
fun main() {
val config = serverConfig {
developmentMode = true
rootPath = "/api"
module {
// Configure application
configureRouting()
configurePlugins()
}
}
embeddedServer(Netty, rootConfig = config) {
// Additional engine configuration
}.start(wait = true)
}
fun Application.configurePlugins() {
install(CallLogging) {
level = Level.INFO
}
}import io.ktor.server.application.*
// Simple plugin with no configuration
val SimpleLoggingPlugin = createApplicationPlugin("SimpleLogging") {
onCall { call ->
println("Processing request: ${call.request.uri}")
}
}
// Plugin with configuration
data class TimingConfig(var enabled: Boolean = true)
val RequestTimingPlugin = createApplicationPlugin(
name = "RequestTiming",
createConfiguration = ::TimingConfig
) {
val enabled = pluginConfig.enabled
if (enabled) {
onCall { call ->
val start = System.currentTimeMillis()
call.attributes.put(StartTimeKey, start)
}
on(ResponseSent) { call ->
val start = call.attributes[StartTimeKey]
val duration = System.currentTimeMillis() - start
println("Request completed in ${duration}ms")
}
}
}
private val StartTimeKey = AttributeKey<Long>("StartTime")
// Install and use the plugins
fun Application.configurePlugins() {
install(SimpleLoggingPlugin)
install(RequestTimingPlugin) {
enabled = environment.developmentMode
}
}val RateLimitPlugin = createRouteScopedPlugin("RateLimit") {
val route = route ?: return@createRouteScopedPlugin
onCall { call ->
val clientIp = call.request.origin.remoteHost
if (isRateLimited(clientIp)) {
call.respond(HttpStatusCode.TooManyRequests)
return@onCall
}
recordRequest(clientIp)
}
}
fun Route.configureRateLimit() {
install(RateLimitPlugin)
}Install with Tessl CLI
npx tessl i tessl/maven-io-ktor--ktor-server-core-iosarm64