Core server functionality for the Ktor asynchronous web framework, providing essential building blocks for HTTP servers including application lifecycle management, routing foundations, request/response handling, and plugin architecture specifically compiled for JVM targets.
—
Response handling functionality for setting status codes, headers, cookies, and sending various types of content back to clients with full type safety and content negotiation support.
Abstract base class for HTTP responses providing access to status, headers, cookies, and content sending pipeline.
/**
* Interface for HTTP responses
*/
interface ApplicationResponse {
/** The application call this response belongs to */
val call: ApplicationCall
/** Pipeline for processing outgoing content */
val pipeline: ApplicationSendPipeline
/** HTTP status code */
val status: HttpStatusCode?
/** Response headers */
val headers: ResponseHeaders
/** Response cookies */
val cookies: ResponseCookies
/** Whether response has been committed */
val isCommitted: Boolean
/** Whether response has been sent */
val isSent: Boolean
/** Set response status code */
fun status(value: HttpStatusCode)
/** Push response (HTTP/2) */
fun push(builder: ResponsePushBuilder)
}Functions for sending various types of content as HTTP responses with automatic content negotiation and serialization.
/**
* Sends response content with automatic serialization
* @param message - Content to send (any serializable object)
* @throws ContentTransformationException if serialization fails
*/
suspend fun ApplicationCall.respond(message: Any)
/**
* Sends response with specific status code
* @param status - HTTP status code
* @param message - Content to send (optional, defaults to empty)
*/
suspend fun ApplicationCall.respond(status: HttpStatusCode, message: Any = "")
/**
* Sends plain text response
* @param text - Text content to send
* @param contentType - Optional content type (defaults to text/plain)
* @param status - Optional HTTP status code
*/
suspend fun ApplicationCall.respondText(
text: String,
contentType: ContentType? = null,
status: HttpStatusCode? = null
)
/**
* Sends byte array response
* @param bytes - Binary content to send
* @param contentType - Optional content type
* @param status - Optional HTTP status code
*/
suspend fun ApplicationCall.respondBytes(
bytes: ByteArray,
contentType: ContentType? = null,
status: HttpStatusCode? = null
)
/**
* Sends HTTP redirect response
* @param url - Target URL for redirect
* @param permanent - Whether redirect is permanent (301) or temporary (302)
*/
suspend fun ApplicationCall.respondRedirect(url: String, permanent: Boolean = false)
/**
* Sends content from kotlinx-io Source
* @param source - Raw source to send
* @param contentType - Optional content type
* @param status - Optional HTTP status code
* @param contentLength - Optional content length
*/
suspend fun ApplicationCall.respondSource(
source: RawSource,
contentType: ContentType? = null,
status: HttpStatusCode? = null,
contentLength: Long? = null
)
/**
* Sends response with binary content producer
* @param contentType - Optional content type
* @param status - Optional HTTP status code
* @param contentLength - Optional content length
* @param producer - Function that writes content to ByteWriteChannel
*/
suspend fun ApplicationCall.respondBytesWriter(
contentType: ContentType? = null,
status: HttpStatusCode? = null,
contentLength: Long? = null,
producer: suspend ByteWriteChannel.() -> Unit
)
/**
* Sends output stream content
* @param contentType - Content type for response
* @param status - HTTP status code
* @param producer - Function that writes content to output stream
*/
suspend fun ApplicationCall.respondOutputStream(
contentType: ContentType? = null,
status: HttpStatusCode? = null,
producer: suspend OutputStream.() -> Unit
)
/**
* Sends response with nullable content (type-safe)
* @param message - Content to send (can be null)
*/
suspend inline fun <reified T> ApplicationCall.respondNullable(message: T)
/**
* Sends response with nullable content and status
* @param status - HTTP status code
* @param message - Content to send (can be null)
*/
suspend inline fun <reified T> ApplicationCall.respondNullable(status: HttpStatusCode, message: T)
/**
* Sends response with specific type information
* @param message - Content to send
* @param messageType - Type information for serialization
*/
suspend fun ApplicationCall.respond(message: Any?, messageType: TypeInfo)
/**
* Sends response with status and type information
* @param status - HTTP status code
* @param message - Content to send
* @param messageType - Type information for serialization
*/
suspend fun ApplicationCall.respond(
status: HttpStatusCode,
message: Any?,
messageType: TypeInfo
)Interface for manipulating HTTP response headers with type-safe access patterns.
/**
* Interface for response header manipulation
*/
abstract class ResponseHeaders {
/** Append header value */
abstract fun append(name: String, value: String)
/** Append header with date value */
abstract fun append(name: String, value: Date)
/** Append header with int value */
abstract fun append(name: String, value: Int)
/** Get header values */
abstract operator fun get(name: String): String?
/** Check if header exists */
abstract fun contains(name: String): Boolean
/** Get all header names */
abstract fun names(): Set<String>
/** Get all values for header */
abstract fun values(name: String): List<String>
/** Remove all values for header */
abstract fun remove(name: String)
/** Clear all headers */
abstract fun clear()
}
/** Set Content-Type header */
fun ResponseHeaders.contentType(contentType: ContentType) =
append(HttpHeaders.ContentType, contentType.toString())
/** Set Content-Length header */
fun ResponseHeaders.contentLength(length: Long) =
append(HttpHeaders.ContentLength, length.toString())
/** Set Cache-Control header */
fun ResponseHeaders.cacheControl(cacheControl: CacheControl) =
append(HttpHeaders.CacheControl, cacheControl.toString())Interface for managing HTTP response cookies with support for various cookie attributes.
/**
* Interface for response cookie management
*/
interface ResponseCookies {
/** Append cookie to response */
fun append(cookie: Cookie)
/** Append cookie with name and value */
fun append(name: String, value: String, encoding: CookieEncoding = CookieEncoding.URI_ENCODING)
}
/**
* HTTP cookie representation
*/
data class Cookie(
val name: String,
val value: String,
val encoding: CookieEncoding = CookieEncoding.URI_ENCODING,
val maxAge: Int = 0,
val expires: Date? = null,
val domain: String? = null,
val path: String? = null,
val secure: Boolean = false,
val httpOnly: Boolean = false,
val extensions: Map<String, String?> = emptyMap()
)
enum class CookieEncoding {
URI_ENCODING,
DQUOTES,
RAW
}Pipeline system for processing and transforming outgoing response content through interceptor chains.
/**
* Pipeline for processing outgoing response content
*/
class ApplicationSendPipeline : Pipeline<Any, ApplicationCall> {
companion object {
/** Before phase for pre-processing */
val Before: PipelinePhase = PipelinePhase("Before")
/** Transform phase for content transformation */
val Transform: PipelinePhase = PipelinePhase("Transform")
/** After phase for post-processing */
val After: PipelinePhase = PipelinePhase("After")
/** Engine phase for final processing */
val Engine: PipelinePhase = PipelinePhase("Engine")
}
}
/**
* Content converter for response serialization
*/
interface ContentConverter {
/** Convert content for sending */
suspend fun convertForSend(
context: PipelineContext<Any, ApplicationCall>,
contentType: ContentType,
value: Any
): Any?
}Enumeration of HTTP status codes with standard descriptions and utility functions.
/**
* HTTP status code enumeration
*/
enum class HttpStatusCode(val value: Int, val description: String) {
// 2xx Success
OK(200, "OK"),
Created(201, "Created"),
Accepted(202, "Accepted"),
NoContent(204, "No Content"),
// 3xx Redirection
MovedPermanently(301, "Moved Permanently"),
Found(302, "Found"),
SeeOther(303, "See Other"),
NotModified(304, "Not Modified"),
// 4xx Client Error
BadRequest(400, "Bad Request"),
Unauthorized(401, "Unauthorized"),
Forbidden(403, "Forbidden"),
NotFound(404, "Not Found"),
MethodNotAllowed(405, "Method Not Allowed"),
Conflict(409, "Conflict"),
UnprocessableEntity(422, "Unprocessable Entity"),
// 5xx Server Error
InternalServerError(500, "Internal Server Error"),
NotImplemented(501, "Not Implemented"),
BadGateway(502, "Bad Gateway"),
ServiceUnavailable(503, "Service Unavailable");
/** Check if status code indicates success (2xx) */
val isSuccess: Boolean get() = value in 200..299
/** Check if status code indicates informational (1xx) */
val isInformational: Boolean get() = value in 100..199
/** Check if status code indicates redirection (3xx) */
val isRedirection: Boolean get() = value in 300..399
/** Check if status code indicates client error (4xx) */
val isClientError: Boolean get() = value in 400..499
/** Check if status code indicates server error (5xx) */
val isServerError: Boolean get() = value in 500..599
}Content type definitions and utilities for response content negotiation.
/**
* Content type representation
*/
data class ContentType(
val contentType: String,
val contentSubtype: String,
val parameters: List<HeaderValueParam> = emptyList()
) {
companion object {
// Text types
val Text = ContentType("text", "*")
val Text_Plain = ContentType("text", "plain")
val Text_Html = ContentType("text", "html")
val Text_CSS = ContentType("text", "css")
val Text_JavaScript = ContentType("text", "javascript")
// Application types
val Application = ContentType("application", "*")
val Application_Json = ContentType("application", "json")
val Application_Xml = ContentType("application", "xml")
val Application_OctetStream = ContentType("application", "octet-stream")
val Application_FormUrlEncoded = ContentType("application", "x-www-form-urlencoded")
// Multipart types
val MultiPart = ContentType("multipart", "*")
val MultiPart_FormData = ContentType("multipart", "form-data")
}
/** Create content type with charset parameter */
fun withCharset(charset: Charset): ContentType
/** Create content type with parameter */
fun withParameter(name: String, value: String): ContentType
}Usage Examples:
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.http.*
// Basic responses
routing {
get("/") {
call.respondText("Hello, World!")
}
get("/json") {
call.respond(mapOf("message" to "Hello", "timestamp" to System.currentTimeMillis()))
}
get("/status") {
call.respond(HttpStatusCode.OK, "Service is running")
}
}
// Custom content types and headers
routing {
get("/custom") {
call.response.headers.append(HttpHeaders.CacheControl, "no-cache")
call.response.headers.contentLength(12)
call.respondText("Custom response", ContentType.Text.Html)
}
get("/file") {
val file = File("document.pdf")
call.response.headers.append(
HttpHeaders.ContentDisposition,
"attachment; filename=document.pdf"
)
call.respondFile(file)
}
}
// Cookie management
routing {
post("/login") {
// Set authentication cookie
call.response.cookies.append(
Cookie(
name = "auth_token",
value = "abc123",
maxAge = 3600,
httpOnly = true,
secure = true,
path = "/"
)
)
call.respond(HttpStatusCode.OK, "Logged in")
}
post("/logout") {
// Clear authentication cookie
call.response.cookies.append(
Cookie(
name = "auth_token",
value = "",
maxAge = 0
)
)
call.respond(HttpStatusCode.OK, "Logged out")
}
}
// Redirects
routing {
get("/old-path") {
call.respondRedirect("/new-path", permanent = true)
}
post("/submit") {
// Process form submission
call.respondRedirect("/success")
}
}
// Streaming responses
routing {
get("/stream") {
call.respondOutputStream(ContentType.Text.Plain) {
for (i in 1..100) {
write("Line $i\n".toByteArray())
flush()
Thread.sleep(100)
}
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-io-ktor--ktor-server-core-jvm