0
# Request and Response Handling
1
2
Abstract base classes for HTTP request and response processing with Netty channel integration and coroutine support.
3
4
## Capabilities
5
6
### NettyApplicationCall
7
8
Abstract base class for Netty-specific application calls that manages the complete request-response lifecycle.
9
10
```kotlin { .api }
11
/**
12
* Base class for Netty-specific application calls
13
*/
14
abstract class NettyApplicationCall(
15
application: Application,
16
public val context: ChannelHandlerContext,
17
private val requestMessage: Any,
18
) : BaseApplicationCall(application) {
19
20
/**
21
* Netty channel handler context for low-level channel operations
22
*/
23
val context: ChannelHandlerContext
24
25
/**
26
* HTTP request object (implementation-specific)
27
*/
28
abstract override val request: NettyApplicationRequest
29
30
/**
31
* HTTP response object (implementation-specific)
32
*/
33
abstract override val response: NettyApplicationResponse
34
35
/**
36
* Coroutine job for response write operations
37
*/
38
val responseWriteJob: Job
39
}
40
```
41
42
**Usage Context:**
43
44
The NettyApplicationCall is typically used within Ktor's request processing pipeline and provides access to Netty-specific functionality:
45
46
```kotlin
47
// In a Ktor route handler
48
get("/netty-info") {
49
val nettyCall = call as? NettyApplicationCall
50
if (nettyCall != null) {
51
// Access Netty channel context
52
val remoteAddress = nettyCall.context.channel().remoteAddress()
53
call.respondText("Client address: $remoteAddress")
54
}
55
}
56
```
57
58
### NettyApplicationRequest
59
60
Abstract base class for HTTP requests with Netty channel integration and coroutine-aware body processing.
61
62
```kotlin { .api }
63
/**
64
* Base class for Netty-specific HTTP requests
65
*/
66
abstract class NettyApplicationRequest(
67
call: PipelineCall,
68
override val coroutineContext: CoroutineContext,
69
public val context: ChannelHandlerContext,
70
private val requestBodyChannel: ByteReadChannel,
71
protected val uri: String,
72
internal val keepAlive: Boolean
73
) : BaseApplicationRequest(call), CoroutineScope {
74
75
/**
76
* Netty channel handler context
77
*/
78
val context: ChannelHandlerContext
79
80
/**
81
* Parsed query parameters from the request URI
82
*/
83
final override val queryParameters: Parameters
84
85
/**
86
* Raw (undecoded) query parameters
87
*/
88
override val rawQueryParameters: Parameters
89
90
/**
91
* Request cookies collection
92
*/
93
override val cookies: RequestCookies
94
95
/**
96
* Byte channel for reading request body content
97
*/
98
override val engineReceiveChannel: ByteReadChannel
99
100
/**
101
* Close the request and release associated resources
102
*/
103
fun close()
104
}
105
```
106
107
**Usage Examples:**
108
109
```kotlin
110
// Accessing request information in route handlers
111
post("/upload") {
112
val nettyRequest = call.request as? NettyApplicationRequest
113
if (nettyRequest != null) {
114
// Access raw query parameters (useful for debugging)
115
val rawParams = nettyRequest.rawQueryParameters
116
println("Raw query params: $rawParams")
117
118
// Read request body
119
val bodyText = nettyRequest.engineReceiveChannel.readUTF8Line()
120
call.respondText("Received: $bodyText")
121
}
122
}
123
124
// Working with cookies
125
get("/session") {
126
val sessionId = call.request.cookies["sessionId"]
127
if (sessionId != null) {
128
call.respondText("Session ID: ${sessionId.value}")
129
} else {
130
call.respondText("No session found")
131
}
132
}
133
```
134
135
### NettyApplicationResponse
136
137
Abstract base class for HTTP responses with Netty channel integration and asynchronous response writing.
138
139
```kotlin { .api }
140
/**
141
* Base class for Netty-specific HTTP responses
142
*/
143
abstract class NettyApplicationResponse(
144
call: NettyApplicationCall,
145
protected val context: ChannelHandlerContext,
146
protected val engineContext: CoroutineContext,
147
protected val userContext: CoroutineContext
148
) : BaseApplicationResponse(call) {
149
150
/**
151
* Response message object (protocol-specific)
152
*/
153
lateinit var responseMessage: Any
154
155
/**
156
* Cancel the response operation
157
*/
158
fun cancel()
159
160
companion object {
161
/**
162
* Cached HTTP status objects for performance optimization
163
*/
164
val responseStatusCache: Array<HttpResponseStatus?>
165
}
166
}
167
```
168
169
**Usage Examples:**
170
171
```kotlin
172
// Custom response handling
173
get("/custom-response") {
174
val nettyResponse = call.response as? NettyApplicationResponse
175
if (nettyResponse != null) {
176
// Cancel response if needed
177
if (someCondition) {
178
nettyResponse.cancel()
179
return@get
180
}
181
}
182
183
call.respondText("Normal response")
184
}
185
```
186
187
### NettyApplicationRequestHeaders
188
189
Implementation of HTTP request headers backed by Netty's HttpRequest.
190
191
```kotlin { .api }
192
/**
193
* Headers implementation for Netty HTTP requests
194
*/
195
class NettyApplicationRequestHeaders(request: HttpRequest) : Headers {
196
// Implements Headers interface methods for accessing HTTP headers
197
}
198
```
199
200
**Usage Examples:**
201
202
```kotlin
203
get("/headers") {
204
val headers = call.request.headers
205
val userAgent = headers["User-Agent"]
206
val acceptLanguage = headers["Accept-Language"]
207
208
call.respondText("""
209
User Agent: $userAgent
210
Accept Language: $acceptLanguage
211
All headers: ${headers.entries().joinToString()}
212
""".trimIndent())
213
}
214
```
215
216
### Request Body Processing
217
218
NettyApplicationRequest provides coroutine-aware body reading through ByteReadChannel:
219
220
```kotlin
221
// Reading different content types
222
post("/data") {
223
when (call.request.contentType()?.contentType) {
224
"application/json" -> {
225
val json = call.request.engineReceiveChannel.readUTF8Line()
226
// Process JSON
227
call.respondText("JSON received: $json")
228
}
229
230
"text/plain" -> {
231
val text = call.request.engineReceiveChannel.readUTF8Line()
232
call.respondText("Text received: $text")
233
}
234
235
"multipart/form-data" -> {
236
// Handle multipart data
237
val multipart = call.receiveMultipart()
238
// Process multipart content
239
}
240
}
241
}
242
```
243
244
### Connection Management
245
246
Access to connection-level information through the Netty channel context:
247
248
```kotlin
249
get("/connection-info") {
250
val nettyCall = call as? NettyApplicationCall
251
if (nettyCall != null) {
252
val channel = nettyCall.context.channel()
253
val localAddress = channel.localAddress()
254
val remoteAddress = channel.remoteAddress()
255
val isActive = channel.isActive
256
val isWritable = channel.isWritable
257
258
call.respondText("""
259
Local: $localAddress
260
Remote: $remoteAddress
261
Active: $isActive
262
Writable: $isWritable
263
""".trimIndent())
264
}
265
}
266
```
267
268
### Error Handling
269
270
The request and response classes integrate with Ktor's error handling mechanisms:
271
272
```kotlin
273
// Error handling in request processing
274
install(StatusPages) {
275
exception<Throwable> { call, cause ->
276
val nettyCall = call as? NettyApplicationCall
277
if (nettyCall != null) {
278
// Log channel information for debugging
279
logger.error("Error in channel: ${nettyCall.context.channel()}", cause)
280
}
281
282
call.respondText("Internal Server Error", status = HttpStatusCode.InternalServerError)
283
}
284
}
285
```