CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-ktor--ktor-http-jvm

JVM-specific HTTP utilities and extensions for the Ktor framework providing URL utilities, file content type detection, HTTP message properties, and content handling for JVM platforms

Pending
Overview
Eval results
Files

message-properties.mddocs/

Message Properties

HTTP message property extraction and manipulation with JVM-specific Date support, providing convenient access to common HTTP headers with proper type conversion.

Capabilities

HttpMessage Interface

Base interface for HTTP messages (requests and responses) providing header access.

/**
 * Base interface for HTTP messages
 */
interface HttpMessage {
    /**
     * HTTP headers for this message
     */
    val headers: Headers
}

/**
 * Base interface for HTTP message builders
 */
interface HttpMessageBuilder {
    /**
     * Mutable HTTP headers for this message
     */
    val headers: HeadersBuilder
}

Common Message Properties

Functions for extracting common HTTP message properties with proper type conversion.

/**
 * Get Content-Type header value
 * @return ContentType instance or null if not present
 */
fun HttpMessage.contentType(): ContentType?

/**
 * Get Content-Type header value from builder
 * @return ContentType instance or null if not present
 */
fun HttpMessageBuilder.contentType(): ContentType?

/**
 * Set Content-Type header
 * @param contentType content type to set
 */
fun HttpMessageBuilder.contentType(contentType: ContentType)

/**
 * Get Content-Length header value
 * @return content length as Long or null if not present
 */
fun HttpMessage.contentLength(): Long?

/**
 * Get Content-Length header value from builder
 * @return content length as Long or null if not present
 */
fun HttpMessageBuilder.contentLength(): Long?

/**
 * Get charset from Content-Type header
 * @return Charset instance or null if not specified
 */
fun HttpMessage.charset(): Charset?

/**
 * Get charset from Content-Type header in builder
 * @return Charset instance or null if not specified
 */
fun HttpMessageBuilder.charset(): Charset?

/**
 * Get ETag header value
 * @return ETag value or null if not present
 */
fun HttpMessage.etag(): String?

/**
 * Get ETag header value from builder
 * @return ETag value or null if not present
 */
fun HttpMessageBuilder.etag(): String?

/**
 * Set If-None-Match header
 * @param etag ETag value to set
 */
fun HttpMessageBuilder.ifNoneMatch(etag: String)

/**
 * Set max age cache control
 * @param seconds max age in seconds
 */
fun HttpMessageBuilder.maxAge(seconds: Int)

/**
 * Set User-Agent header
 * @param userAgent user agent string
 */
fun HttpMessageBuilder.userAgent(userAgent: String)

Cache Control Properties

Functions for working with Cache-Control headers and caching directives.

/**
 * Get Cache-Control directives
 * @return List of CacheControl instances
 */
fun HttpMessage.cacheControl(): List<CacheControl>

/**
 * Get Vary header values
 * @return List of header names that affect caching
 */
fun HttpMessage.vary(): List<String>

/**
 * Get Vary header values from builder
 * @return List of header names that affect caching
 */
fun HttpMessageBuilder.vary(): List<String>

Cookie Properties

Functions for accessing cookies in HTTP messages.

/**
 * Get Set-Cookie header values (response)
 * @return List of Cookie instances from Set-Cookie headers
 */
fun HttpMessage.setCookie(): List<Cookie>

/**
 * Get cookies from Cookie header (request)
 * @return List of Cookie instances from Cookie header
 */
fun HttpMessageBuilder.cookies(): List<Cookie>

JVM-specific Date Properties

JVM-specific functions using java.util.Date for date-related HTTP headers.

/**
 * Get Date header value (JVM-specific)
 * @return Date instance or null if not present
 */
fun HttpMessage.date(): Date?

/**
 * Get Last-Modified header value (JVM-specific)
 * @return Date instance or null if not present
 */
fun HttpMessage.lastModified(): Date?

/**
 * Get Last-Modified header value from builder (JVM-specific)
 * @return Date instance or null if not present
 */
fun HttpMessageBuilder.lastModified(): Date?

/**
 * Get Expires header value (JVM-specific)
 * @return Date instance or null if not present
 */
fun HttpMessage.expires(): Date?

/**
 * Get Expires header value from builder (JVM-specific)
 * @return Date instance or null if not present
 */
fun HttpMessageBuilder.expires(): Date?

/**
 * Set If-Modified-Since header (JVM-specific)
 * @param date date to set
 */
fun HttpMessageBuilder.ifModifiedSince(date: Date)

Application Response Properties

Utility functions for common response properties.

/**
 * Set ETag header in response
 * @param value ETag value to set
 */
fun HeadersBuilder.etag(value: String)

Usage Examples:

import io.ktor.http.*
import java.util.*
import java.nio.charset.Charset

// Working with HttpMessage (typically from request/response)
class ExampleHttpMessage(override val headers: Headers) : HttpMessage

val headers = headers {
    append(HttpHeaders.ContentType, "application/json; charset=utf-8")
    append(HttpHeaders.ContentLength, "1024")
    append(HttpHeaders.ETag, "\"12345\"")
    append(HttpHeaders.CacheControl, "max-age=3600, public")
    append(HttpHeaders.LastModified, "Wed, 21 Oct 2015 07:28:00 GMT")
}

val message = ExampleHttpMessage(headers)

// Extract common properties
val contentType = message.contentType()
println("Content-Type: $contentType") // application/json

val contentLength = message.contentLength()
println("Content-Length: $contentLength") // 1024

val charset = message.charset()
println("Charset: $charset") // UTF-8

val etag = message.etag()
println("ETag: $etag") // "12345"

// JVM-specific date properties
val lastModified = message.lastModified()
println("Last-Modified: $lastModified") // Wed Oct 21 07:28:00 GMT 2015

val date = message.date() // null if not present
val expires = message.expires() // null if not present

// Cache control
val cacheDirectives = message.cacheControl()
cacheDirectives.forEach { directive ->
    when (directive) {
        is CacheControl.MaxAge -> println("Max-Age: ${directive.maxAgeSeconds}")
        is CacheControl.NoCache -> println("No-Cache")
        is CacheControl.NoStore -> println("No-Store")
    }
}

// Working with HttpMessageBuilder (typically when building requests/responses)
class ExampleMessageBuilder(override val headers: HeadersBuilder) : HttpMessageBuilder

val builder = ExampleMessageBuilder(HeadersBuilder())

// Set properties using builder functions
builder.contentType(ContentType.Application.Json.withCharset(Charsets.UTF_8))
builder.userAgent("MyApp/1.0")
builder.maxAge(3600)
builder.ifNoneMatch("\"etag-value\"")

// JVM-specific date setting
val now = Date()
builder.ifModifiedSince(now)

// Access properties from builder
val builderContentType = builder.contentType()
val builderCharset = builder.charset()

// Cookie handling in messages
val cookieHeaders = headers {
    append(HttpHeaders.SetCookie, "sessionId=abc123; HttpOnly; Secure")
    append(HttpHeaders.SetCookie, "theme=dark; Path=/; Max-Age=86400")
}

val messageWithCookies = ExampleHttpMessage(cookieHeaders)
val cookies = messageWithCookies.setCookie()
cookies.forEach { cookie ->
    println("Cookie: ${cookie.name}=${cookie.value}")
    if (cookie.httpOnly) println("  HttpOnly")
    if (cookie.secure) println("  Secure")
}

// Vary header handling
val varyHeaders = headers {
    append(HttpHeaders.Vary, "Accept-Encoding, User-Agent")
}
val varyMessage = ExampleHttpMessage(varyHeaders)
val varyValues = varyMessage.vary()
println("Varies on: ${varyValues.joinToString()}") // Accept-Encoding, User-Agent

// Utility functions for response building
val responseHeaders = HeadersBuilder()
responseHeaders.etag("\"resource-version-123\"")
responseHeaders.append(HttpHeaders.CacheControl, "private, max-age=300")

// Common patterns for request processing
fun processRequest(request: HttpMessage): String {
    val acceptedType = request.contentType()
    val contentLength = request.contentLength()
    val userCharset = request.charset()
    
    return when {
        acceptedType?.match(ContentType.Application.Json) == true -> "Processing JSON"
        acceptedType?.match(ContentType.Application.FormUrlEncoded) == true -> "Processing form data"
        contentLength != null && contentLength > 1_000_000 -> "Content too large"
        else -> "Processing generic content"
    }
}

// Common patterns for response building
fun buildCacheableResponse(builder: HttpMessageBuilder, content: String, etag: String) {
    builder.contentType(ContentType.Text.Html.withCharset(Charsets.UTF_8))
    builder.ifNoneMatch(etag)
    builder.maxAge(3600) // 1 hour
    
    // Set response headers
    builder.headers.apply {
        etag(etag)
        append(HttpHeaders.Vary, "Accept-Encoding")
    }
}

// Conditional request handling
fun handleConditionalRequest(request: HttpMessage, resourceETag: String, lastModified: Date): Boolean {
    val requestETag = request.etag()
    val ifModifiedSince = request.lastModified()
    
    // Check if resource has been modified
    val etagMatches = requestETag == resourceETag
    val notModifiedSince = ifModifiedSince?.let { it >= lastModified } ?: false
    
    return etagMatches || notModifiedSince
}

// Content negotiation
fun negotiateContentType(request: HttpMessage): ContentType {
    val acceptHeader = request.headers[HttpHeaders.Accept]
    return when {
        acceptHeader?.contains("application/json") == true -> ContentType.Application.Json
        acceptHeader?.contains("text/html") == true -> ContentType.Text.Html
        acceptHeader?.contains("application/xml") == true -> ContentType.Application.Xml
        else -> ContentType.Text.Plain
    }
}

Types

All types are defined above in their respective capability sections.

Install with Tessl CLI

npx tessl i tessl/maven-io-ktor--ktor-http-jvm

docs

authentication.md

content-handling.md

content-types.md

cookie-management.md

headers-parameters.md

http-core-types.md

index.md

message-properties.md

multipart-data.md

url-encoding.md

url-handling.md

tile.json