0
# Message Properties
1
2
HTTP message property extraction and manipulation with JVM-specific Date support, providing convenient access to common HTTP headers with proper type conversion.
3
4
## Capabilities
5
6
### HttpMessage Interface
7
8
Base interface for HTTP messages (requests and responses) providing header access.
9
10
```kotlin { .api }
11
/**
12
* Base interface for HTTP messages
13
*/
14
interface HttpMessage {
15
/**
16
* HTTP headers for this message
17
*/
18
val headers: Headers
19
}
20
21
/**
22
* Base interface for HTTP message builders
23
*/
24
interface HttpMessageBuilder {
25
/**
26
* Mutable HTTP headers for this message
27
*/
28
val headers: HeadersBuilder
29
}
30
```
31
32
### Common Message Properties
33
34
Functions for extracting common HTTP message properties with proper type conversion.
35
36
```kotlin { .api }
37
/**
38
* Get Content-Type header value
39
* @return ContentType instance or null if not present
40
*/
41
fun HttpMessage.contentType(): ContentType?
42
43
/**
44
* Get Content-Type header value from builder
45
* @return ContentType instance or null if not present
46
*/
47
fun HttpMessageBuilder.contentType(): ContentType?
48
49
/**
50
* Set Content-Type header
51
* @param contentType content type to set
52
*/
53
fun HttpMessageBuilder.contentType(contentType: ContentType)
54
55
/**
56
* Get Content-Length header value
57
* @return content length as Long or null if not present
58
*/
59
fun HttpMessage.contentLength(): Long?
60
61
/**
62
* Get Content-Length header value from builder
63
* @return content length as Long or null if not present
64
*/
65
fun HttpMessageBuilder.contentLength(): Long?
66
67
/**
68
* Get charset from Content-Type header
69
* @return Charset instance or null if not specified
70
*/
71
fun HttpMessage.charset(): Charset?
72
73
/**
74
* Get charset from Content-Type header in builder
75
* @return Charset instance or null if not specified
76
*/
77
fun HttpMessageBuilder.charset(): Charset?
78
79
/**
80
* Get ETag header value
81
* @return ETag value or null if not present
82
*/
83
fun HttpMessage.etag(): String?
84
85
/**
86
* Get ETag header value from builder
87
* @return ETag value or null if not present
88
*/
89
fun HttpMessageBuilder.etag(): String?
90
91
/**
92
* Set If-None-Match header
93
* @param etag ETag value to set
94
*/
95
fun HttpMessageBuilder.ifNoneMatch(etag: String)
96
97
/**
98
* Set max age cache control
99
* @param seconds max age in seconds
100
*/
101
fun HttpMessageBuilder.maxAge(seconds: Int)
102
103
/**
104
* Set User-Agent header
105
* @param userAgent user agent string
106
*/
107
fun HttpMessageBuilder.userAgent(userAgent: String)
108
```
109
110
### Cache Control Properties
111
112
Functions for working with Cache-Control headers and caching directives.
113
114
```kotlin { .api }
115
/**
116
* Get Cache-Control directives
117
* @return List of CacheControl instances
118
*/
119
fun HttpMessage.cacheControl(): List<CacheControl>
120
121
/**
122
* Get Vary header values
123
* @return List of header names that affect caching
124
*/
125
fun HttpMessage.vary(): List<String>
126
127
/**
128
* Get Vary header values from builder
129
* @return List of header names that affect caching
130
*/
131
fun HttpMessageBuilder.vary(): List<String>
132
```
133
134
### Cookie Properties
135
136
Functions for accessing cookies in HTTP messages.
137
138
```kotlin { .api }
139
/**
140
* Get Set-Cookie header values (response)
141
* @return List of Cookie instances from Set-Cookie headers
142
*/
143
fun HttpMessage.setCookie(): List<Cookie>
144
145
/**
146
* Get cookies from Cookie header (request)
147
* @return List of Cookie instances from Cookie header
148
*/
149
fun HttpMessageBuilder.cookies(): List<Cookie>
150
```
151
152
### JVM-specific Date Properties
153
154
JVM-specific functions using java.util.Date for date-related HTTP headers.
155
156
```kotlin { .api }
157
/**
158
* Get Date header value (JVM-specific)
159
* @return Date instance or null if not present
160
*/
161
fun HttpMessage.date(): Date?
162
163
/**
164
* Get Last-Modified header value (JVM-specific)
165
* @return Date instance or null if not present
166
*/
167
fun HttpMessage.lastModified(): Date?
168
169
/**
170
* Get Last-Modified header value from builder (JVM-specific)
171
* @return Date instance or null if not present
172
*/
173
fun HttpMessageBuilder.lastModified(): Date?
174
175
/**
176
* Get Expires header value (JVM-specific)
177
* @return Date instance or null if not present
178
*/
179
fun HttpMessage.expires(): Date?
180
181
/**
182
* Get Expires header value from builder (JVM-specific)
183
* @return Date instance or null if not present
184
*/
185
fun HttpMessageBuilder.expires(): Date?
186
187
/**
188
* Set If-Modified-Since header (JVM-specific)
189
* @param date date to set
190
*/
191
fun HttpMessageBuilder.ifModifiedSince(date: Date)
192
```
193
194
### Application Response Properties
195
196
Utility functions for common response properties.
197
198
```kotlin { .api }
199
/**
200
* Set ETag header in response
201
* @param value ETag value to set
202
*/
203
fun HeadersBuilder.etag(value: String)
204
```
205
206
**Usage Examples:**
207
208
```kotlin
209
import io.ktor.http.*
210
import java.util.*
211
import java.nio.charset.Charset
212
213
// Working with HttpMessage (typically from request/response)
214
class ExampleHttpMessage(override val headers: Headers) : HttpMessage
215
216
val headers = headers {
217
append(HttpHeaders.ContentType, "application/json; charset=utf-8")
218
append(HttpHeaders.ContentLength, "1024")
219
append(HttpHeaders.ETag, "\"12345\"")
220
append(HttpHeaders.CacheControl, "max-age=3600, public")
221
append(HttpHeaders.LastModified, "Wed, 21 Oct 2015 07:28:00 GMT")
222
}
223
224
val message = ExampleHttpMessage(headers)
225
226
// Extract common properties
227
val contentType = message.contentType()
228
println("Content-Type: $contentType") // application/json
229
230
val contentLength = message.contentLength()
231
println("Content-Length: $contentLength") // 1024
232
233
val charset = message.charset()
234
println("Charset: $charset") // UTF-8
235
236
val etag = message.etag()
237
println("ETag: $etag") // "12345"
238
239
// JVM-specific date properties
240
val lastModified = message.lastModified()
241
println("Last-Modified: $lastModified") // Wed Oct 21 07:28:00 GMT 2015
242
243
val date = message.date() // null if not present
244
val expires = message.expires() // null if not present
245
246
// Cache control
247
val cacheDirectives = message.cacheControl()
248
cacheDirectives.forEach { directive ->
249
when (directive) {
250
is CacheControl.MaxAge -> println("Max-Age: ${directive.maxAgeSeconds}")
251
is CacheControl.NoCache -> println("No-Cache")
252
is CacheControl.NoStore -> println("No-Store")
253
}
254
}
255
256
// Working with HttpMessageBuilder (typically when building requests/responses)
257
class ExampleMessageBuilder(override val headers: HeadersBuilder) : HttpMessageBuilder
258
259
val builder = ExampleMessageBuilder(HeadersBuilder())
260
261
// Set properties using builder functions
262
builder.contentType(ContentType.Application.Json.withCharset(Charsets.UTF_8))
263
builder.userAgent("MyApp/1.0")
264
builder.maxAge(3600)
265
builder.ifNoneMatch("\"etag-value\"")
266
267
// JVM-specific date setting
268
val now = Date()
269
builder.ifModifiedSince(now)
270
271
// Access properties from builder
272
val builderContentType = builder.contentType()
273
val builderCharset = builder.charset()
274
275
// Cookie handling in messages
276
val cookieHeaders = headers {
277
append(HttpHeaders.SetCookie, "sessionId=abc123; HttpOnly; Secure")
278
append(HttpHeaders.SetCookie, "theme=dark; Path=/; Max-Age=86400")
279
}
280
281
val messageWithCookies = ExampleHttpMessage(cookieHeaders)
282
val cookies = messageWithCookies.setCookie()
283
cookies.forEach { cookie ->
284
println("Cookie: ${cookie.name}=${cookie.value}")
285
if (cookie.httpOnly) println(" HttpOnly")
286
if (cookie.secure) println(" Secure")
287
}
288
289
// Vary header handling
290
val varyHeaders = headers {
291
append(HttpHeaders.Vary, "Accept-Encoding, User-Agent")
292
}
293
val varyMessage = ExampleHttpMessage(varyHeaders)
294
val varyValues = varyMessage.vary()
295
println("Varies on: ${varyValues.joinToString()}") // Accept-Encoding, User-Agent
296
297
// Utility functions for response building
298
val responseHeaders = HeadersBuilder()
299
responseHeaders.etag("\"resource-version-123\"")
300
responseHeaders.append(HttpHeaders.CacheControl, "private, max-age=300")
301
302
// Common patterns for request processing
303
fun processRequest(request: HttpMessage): String {
304
val acceptedType = request.contentType()
305
val contentLength = request.contentLength()
306
val userCharset = request.charset()
307
308
return when {
309
acceptedType?.match(ContentType.Application.Json) == true -> "Processing JSON"
310
acceptedType?.match(ContentType.Application.FormUrlEncoded) == true -> "Processing form data"
311
contentLength != null && contentLength > 1_000_000 -> "Content too large"
312
else -> "Processing generic content"
313
}
314
}
315
316
// Common patterns for response building
317
fun buildCacheableResponse(builder: HttpMessageBuilder, content: String, etag: String) {
318
builder.contentType(ContentType.Text.Html.withCharset(Charsets.UTF_8))
319
builder.ifNoneMatch(etag)
320
builder.maxAge(3600) // 1 hour
321
322
// Set response headers
323
builder.headers.apply {
324
etag(etag)
325
append(HttpHeaders.Vary, "Accept-Encoding")
326
}
327
}
328
329
// Conditional request handling
330
fun handleConditionalRequest(request: HttpMessage, resourceETag: String, lastModified: Date): Boolean {
331
val requestETag = request.etag()
332
val ifModifiedSince = request.lastModified()
333
334
// Check if resource has been modified
335
val etagMatches = requestETag == resourceETag
336
val notModifiedSince = ifModifiedSince?.let { it >= lastModified } ?: false
337
338
return etagMatches || notModifiedSince
339
}
340
341
// Content negotiation
342
fun negotiateContentType(request: HttpMessage): ContentType {
343
val acceptHeader = request.headers[HttpHeaders.Accept]
344
return when {
345
acceptHeader?.contains("application/json") == true -> ContentType.Application.Json
346
acceptHeader?.contains("text/html") == true -> ContentType.Text.Html
347
acceptHeader?.contains("application/xml") == true -> ContentType.Application.Xml
348
else -> ContentType.Text.Plain
349
}
350
}
351
```
352
353
## Types
354
355
All types are defined above in their respective capability sections.