0
# Response Processing
1
2
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.
3
4
## Capabilities
5
6
### Application Response
7
8
Abstract base class for HTTP responses providing access to status, headers, cookies, and content sending pipeline.
9
10
```kotlin { .api }
11
/**
12
* Interface for HTTP responses
13
*/
14
interface ApplicationResponse {
15
/** The application call this response belongs to */
16
val call: ApplicationCall
17
/** Pipeline for processing outgoing content */
18
val pipeline: ApplicationSendPipeline
19
/** HTTP status code */
20
val status: HttpStatusCode?
21
/** Response headers */
22
val headers: ResponseHeaders
23
/** Response cookies */
24
val cookies: ResponseCookies
25
/** Whether response has been committed */
26
val isCommitted: Boolean
27
/** Whether response has been sent */
28
val isSent: Boolean
29
30
/** Set response status code */
31
fun status(value: HttpStatusCode)
32
/** Push response (HTTP/2) */
33
fun push(builder: ResponsePushBuilder)
34
}
35
```
36
37
### Content Sending
38
39
Functions for sending various types of content as HTTP responses with automatic content negotiation and serialization.
40
41
```kotlin { .api }
42
/**
43
* Sends response content with automatic serialization
44
* @param message - Content to send (any serializable object)
45
* @throws ContentTransformationException if serialization fails
46
*/
47
suspend fun ApplicationCall.respond(message: Any)
48
49
/**
50
* Sends response with specific status code
51
* @param status - HTTP status code
52
* @param message - Content to send (optional, defaults to empty)
53
*/
54
suspend fun ApplicationCall.respond(status: HttpStatusCode, message: Any = "")
55
56
/**
57
* Sends plain text response
58
* @param text - Text content to send
59
* @param contentType - Optional content type (defaults to text/plain)
60
* @param status - Optional HTTP status code
61
*/
62
suspend fun ApplicationCall.respondText(
63
text: String,
64
contentType: ContentType? = null,
65
status: HttpStatusCode? = null
66
)
67
68
/**
69
* Sends byte array response
70
* @param bytes - Binary content to send
71
* @param contentType - Optional content type
72
* @param status - Optional HTTP status code
73
*/
74
suspend fun ApplicationCall.respondBytes(
75
bytes: ByteArray,
76
contentType: ContentType? = null,
77
status: HttpStatusCode? = null
78
)
79
80
/**
81
* Sends HTTP redirect response
82
* @param url - Target URL for redirect
83
* @param permanent - Whether redirect is permanent (301) or temporary (302)
84
*/
85
suspend fun ApplicationCall.respondRedirect(url: String, permanent: Boolean = false)
86
87
/**
88
* Sends content from kotlinx-io Source
89
* @param source - Raw source to send
90
* @param contentType - Optional content type
91
* @param status - Optional HTTP status code
92
* @param contentLength - Optional content length
93
*/
94
suspend fun ApplicationCall.respondSource(
95
source: RawSource,
96
contentType: ContentType? = null,
97
status: HttpStatusCode? = null,
98
contentLength: Long? = null
99
)
100
101
/**
102
* Sends response with binary content producer
103
* @param contentType - Optional content type
104
* @param status - Optional HTTP status code
105
* @param contentLength - Optional content length
106
* @param producer - Function that writes content to ByteWriteChannel
107
*/
108
suspend fun ApplicationCall.respondBytesWriter(
109
contentType: ContentType? = null,
110
status: HttpStatusCode? = null,
111
contentLength: Long? = null,
112
producer: suspend ByteWriteChannel.() -> Unit
113
)
114
115
/**
116
* Sends output stream content
117
* @param contentType - Content type for response
118
* @param status - HTTP status code
119
* @param producer - Function that writes content to output stream
120
*/
121
suspend fun ApplicationCall.respondOutputStream(
122
contentType: ContentType? = null,
123
status: HttpStatusCode? = null,
124
producer: suspend OutputStream.() -> Unit
125
)
126
127
/**
128
* Sends response with nullable content (type-safe)
129
* @param message - Content to send (can be null)
130
*/
131
suspend inline fun <reified T> ApplicationCall.respondNullable(message: T)
132
133
/**
134
* Sends response with nullable content and status
135
* @param status - HTTP status code
136
* @param message - Content to send (can be null)
137
*/
138
suspend inline fun <reified T> ApplicationCall.respondNullable(status: HttpStatusCode, message: T)
139
140
/**
141
* Sends response with specific type information
142
* @param message - Content to send
143
* @param messageType - Type information for serialization
144
*/
145
suspend fun ApplicationCall.respond(message: Any?, messageType: TypeInfo)
146
147
/**
148
* Sends response with status and type information
149
* @param status - HTTP status code
150
* @param message - Content to send
151
* @param messageType - Type information for serialization
152
*/
153
suspend fun ApplicationCall.respond(
154
status: HttpStatusCode,
155
message: Any?,
156
messageType: TypeInfo
157
)
158
```
159
160
### Response Headers
161
162
Interface for manipulating HTTP response headers with type-safe access patterns.
163
164
```kotlin { .api }
165
/**
166
* Interface for response header manipulation
167
*/
168
abstract class ResponseHeaders {
169
/** Append header value */
170
abstract fun append(name: String, value: String)
171
/** Append header with date value */
172
abstract fun append(name: String, value: Date)
173
/** Append header with int value */
174
abstract fun append(name: String, value: Int)
175
/** Get header values */
176
abstract operator fun get(name: String): String?
177
/** Check if header exists */
178
abstract fun contains(name: String): Boolean
179
/** Get all header names */
180
abstract fun names(): Set<String>
181
/** Get all values for header */
182
abstract fun values(name: String): List<String>
183
/** Remove all values for header */
184
abstract fun remove(name: String)
185
/** Clear all headers */
186
abstract fun clear()
187
}
188
189
/** Set Content-Type header */
190
fun ResponseHeaders.contentType(contentType: ContentType) =
191
append(HttpHeaders.ContentType, contentType.toString())
192
193
/** Set Content-Length header */
194
fun ResponseHeaders.contentLength(length: Long) =
195
append(HttpHeaders.ContentLength, length.toString())
196
197
/** Set Cache-Control header */
198
fun ResponseHeaders.cacheControl(cacheControl: CacheControl) =
199
append(HttpHeaders.CacheControl, cacheControl.toString())
200
```
201
202
### Response Cookies
203
204
Interface for managing HTTP response cookies with support for various cookie attributes.
205
206
```kotlin { .api }
207
/**
208
* Interface for response cookie management
209
*/
210
interface ResponseCookies {
211
/** Append cookie to response */
212
fun append(cookie: Cookie)
213
/** Append cookie with name and value */
214
fun append(name: String, value: String, encoding: CookieEncoding = CookieEncoding.URI_ENCODING)
215
}
216
217
/**
218
* HTTP cookie representation
219
*/
220
data class Cookie(
221
val name: String,
222
val value: String,
223
val encoding: CookieEncoding = CookieEncoding.URI_ENCODING,
224
val maxAge: Int = 0,
225
val expires: Date? = null,
226
val domain: String? = null,
227
val path: String? = null,
228
val secure: Boolean = false,
229
val httpOnly: Boolean = false,
230
val extensions: Map<String, String?> = emptyMap()
231
)
232
233
enum class CookieEncoding {
234
URI_ENCODING,
235
DQUOTES,
236
RAW
237
}
238
```
239
240
### Response Pipeline
241
242
Pipeline system for processing and transforming outgoing response content through interceptor chains.
243
244
```kotlin { .api }
245
/**
246
* Pipeline for processing outgoing response content
247
*/
248
class ApplicationSendPipeline : Pipeline<Any, ApplicationCall> {
249
companion object {
250
/** Before phase for pre-processing */
251
val Before: PipelinePhase = PipelinePhase("Before")
252
/** Transform phase for content transformation */
253
val Transform: PipelinePhase = PipelinePhase("Transform")
254
/** After phase for post-processing */
255
val After: PipelinePhase = PipelinePhase("After")
256
/** Engine phase for final processing */
257
val Engine: PipelinePhase = PipelinePhase("Engine")
258
}
259
}
260
261
/**
262
* Content converter for response serialization
263
*/
264
interface ContentConverter {
265
/** Convert content for sending */
266
suspend fun convertForSend(
267
context: PipelineContext<Any, ApplicationCall>,
268
contentType: ContentType,
269
value: Any
270
): Any?
271
}
272
```
273
274
### HTTP Status Codes
275
276
Enumeration of HTTP status codes with standard descriptions and utility functions.
277
278
```kotlin { .api }
279
/**
280
* HTTP status code enumeration
281
*/
282
enum class HttpStatusCode(val value: Int, val description: String) {
283
// 2xx Success
284
OK(200, "OK"),
285
Created(201, "Created"),
286
Accepted(202, "Accepted"),
287
NoContent(204, "No Content"),
288
289
// 3xx Redirection
290
MovedPermanently(301, "Moved Permanently"),
291
Found(302, "Found"),
292
SeeOther(303, "See Other"),
293
NotModified(304, "Not Modified"),
294
295
// 4xx Client Error
296
BadRequest(400, "Bad Request"),
297
Unauthorized(401, "Unauthorized"),
298
Forbidden(403, "Forbidden"),
299
NotFound(404, "Not Found"),
300
MethodNotAllowed(405, "Method Not Allowed"),
301
Conflict(409, "Conflict"),
302
UnprocessableEntity(422, "Unprocessable Entity"),
303
304
// 5xx Server Error
305
InternalServerError(500, "Internal Server Error"),
306
NotImplemented(501, "Not Implemented"),
307
BadGateway(502, "Bad Gateway"),
308
ServiceUnavailable(503, "Service Unavailable");
309
310
/** Check if status code indicates success (2xx) */
311
val isSuccess: Boolean get() = value in 200..299
312
/** Check if status code indicates informational (1xx) */
313
val isInformational: Boolean get() = value in 100..199
314
/** Check if status code indicates redirection (3xx) */
315
val isRedirection: Boolean get() = value in 300..399
316
/** Check if status code indicates client error (4xx) */
317
val isClientError: Boolean get() = value in 400..499
318
/** Check if status code indicates server error (5xx) */
319
val isServerError: Boolean get() = value in 500..599
320
}
321
```
322
323
### Content Types
324
325
Content type definitions and utilities for response content negotiation.
326
327
```kotlin { .api }
328
/**
329
* Content type representation
330
*/
331
data class ContentType(
332
val contentType: String,
333
val contentSubtype: String,
334
val parameters: List<HeaderValueParam> = emptyList()
335
) {
336
companion object {
337
// Text types
338
val Text = ContentType("text", "*")
339
val Text_Plain = ContentType("text", "plain")
340
val Text_Html = ContentType("text", "html")
341
val Text_CSS = ContentType("text", "css")
342
val Text_JavaScript = ContentType("text", "javascript")
343
344
// Application types
345
val Application = ContentType("application", "*")
346
val Application_Json = ContentType("application", "json")
347
val Application_Xml = ContentType("application", "xml")
348
val Application_OctetStream = ContentType("application", "octet-stream")
349
val Application_FormUrlEncoded = ContentType("application", "x-www-form-urlencoded")
350
351
// Multipart types
352
val MultiPart = ContentType("multipart", "*")
353
val MultiPart_FormData = ContentType("multipart", "form-data")
354
}
355
356
/** Create content type with charset parameter */
357
fun withCharset(charset: Charset): ContentType
358
/** Create content type with parameter */
359
fun withParameter(name: String, value: String): ContentType
360
}
361
```
362
363
**Usage Examples:**
364
365
```kotlin
366
import io.ktor.server.application.*
367
import io.ktor.server.response.*
368
import io.ktor.server.routing.*
369
import io.ktor.http.*
370
371
// Basic responses
372
routing {
373
get("/") {
374
call.respondText("Hello, World!")
375
}
376
377
get("/json") {
378
call.respond(mapOf("message" to "Hello", "timestamp" to System.currentTimeMillis()))
379
}
380
381
get("/status") {
382
call.respond(HttpStatusCode.OK, "Service is running")
383
}
384
}
385
386
// Custom content types and headers
387
routing {
388
get("/custom") {
389
call.response.headers.append(HttpHeaders.CacheControl, "no-cache")
390
call.response.headers.contentLength(12)
391
call.respondText("Custom response", ContentType.Text.Html)
392
}
393
394
get("/file") {
395
val file = File("document.pdf")
396
call.response.headers.append(
397
HttpHeaders.ContentDisposition,
398
"attachment; filename=document.pdf"
399
)
400
call.respondFile(file)
401
}
402
}
403
404
// Cookie management
405
routing {
406
post("/login") {
407
// Set authentication cookie
408
call.response.cookies.append(
409
Cookie(
410
name = "auth_token",
411
value = "abc123",
412
maxAge = 3600,
413
httpOnly = true,
414
secure = true,
415
path = "/"
416
)
417
)
418
call.respond(HttpStatusCode.OK, "Logged in")
419
}
420
421
post("/logout") {
422
// Clear authentication cookie
423
call.response.cookies.append(
424
Cookie(
425
name = "auth_token",
426
value = "",
427
maxAge = 0
428
)
429
)
430
call.respond(HttpStatusCode.OK, "Logged out")
431
}
432
}
433
434
// Redirects
435
routing {
436
get("/old-path") {
437
call.respondRedirect("/new-path", permanent = true)
438
}
439
440
post("/submit") {
441
// Process form submission
442
call.respondRedirect("/success")
443
}
444
}
445
446
// Streaming responses
447
routing {
448
get("/stream") {
449
call.respondOutputStream(ContentType.Text.Plain) {
450
for (i in 1..100) {
451
write("Line $i\n".toByteArray())
452
flush()
453
Thread.sleep(100)
454
}
455
}
456
}
457
}
458
```