CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/kotlin-io-ktor--ktor-http-iosarm64

Ktor HTTP library for iOS ARM64 providing HTTP utilities, content types, headers manipulation, URL building, and HTTP message handling for iOS ARM64 applications built with Kotlin Multiplatform.

Pending
Overview
Eval results
Files

http-message-extensions.mddocs/

HTTP Message Extensions

Extension functions for HTTP messages and message builders providing convenient access to common HTTP headers with automatic parsing and type-safe handling for content types, charset, caching, cookies, and other HTTP properties.

Capabilities

HTTP Message Builder Extensions

Extension functions for building HTTP messages with convenient header setters and getters.

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

/**
 * Get parsed Content-Type header
 * @return ContentType if header exists and is valid, null otherwise
 */
fun HttpMessageBuilder.contentType(): ContentType?

/**
 * Get charset from Content-Type header
 * @return Charset if specified in content type, null otherwise
 */
fun HttpMessageBuilder.charset(): Charset?

/**
 * Get ETag header value
 * @return ETag value if present, null otherwise
 */
fun HttpMessageBuilder.etag(): String?

/**
 * Get Vary header values
 * @return list of header names from Vary header, null if not present
 */
fun HttpMessageBuilder.vary(): List<String>?

/**
 * Get Content-Length header value
 * @return content length if valid, null otherwise
 */
fun HttpMessageBuilder.contentLength(): Long?

/**
 * Parse Set-Cookie headers into Cookie objects
 * @return list of parsed cookies
 */
fun HttpMessageBuilder.cookies(): List<Cookie>

Usage Examples:

import io.ktor.http.*

// Setting content type in message builder
fun buildHttpMessage(): HttpMessage {
    return HttpMessageBuilder().apply {
        contentType(ContentType.Application.Json)
        userAgent("MyApp/1.0")
        maxAge(3600)
        ifNoneMatch("\"etag-123\"")
        
        // Access parsed values
        val type = contentType() // ContentType.Application.Json
        val charset = charset()  // null (no charset specified)
        val length = contentLength() // null (not set)
    }.build()
}

// Working with cookies
fun setCookiesInBuilder(builder: HttpMessageBuilder) {
    builder.headers.append(HttpHeaders.SetCookie, "sessionId=abc123; Path=/; HttpOnly")
    builder.headers.append(HttpHeaders.SetCookie, "theme=dark; Max-Age=3600")
    
    val cookies = builder.cookies()
    println(cookies.size) // 2
    println(cookies[0].name) // "sessionId"
    println(cookies[0].value) // "abc123"
    println(cookies[0].httpOnly) // true
}

HTTP Message Reader Extensions

Extension functions for reading HTTP message properties with automatic parsing.

/**
 * Get parsed Content-Type header from HTTP message
 * @return ContentType if header exists and is valid, null otherwise
 */
fun HttpMessage.contentType(): ContentType?

/**
 * Get charset from Content-Type header in HTTP message
 * @return Charset if specified in content type, null otherwise
 */
fun HttpMessage.charset(): Charset?

/**
 * Get ETag header value from HTTP message
 * @return ETag value if present, null otherwise
 */
fun HttpMessage.etag(): String?

/**
 * Get Vary header values from HTTP message
 * @return list of header names from Vary header, null if not present
 */
fun HttpMessage.vary(): List<String>?

/**
 * Get Content-Length header value from HTTP message
 * @return content length if valid, null otherwise
 */
fun HttpMessage.contentLength(): Long?

/**
 * Parse Set-Cookie headers from HTTP message
 * @return list of parsed Cookie objects
 */
fun HttpMessage.setCookie(): List<Cookie>

/**
 * Parse Cache-Control header values
 * @return list of HeaderValue objects representing cache control directives
 */
fun HttpMessage.cacheControl(): List<HeaderValue>

Usage Examples:

import io.ktor.http.*

// Reading message properties
fun analyzeHttpMessage(message: HttpMessage) {
    // Content analysis
    val contentType = message.contentType()
    println("Content type: ${contentType?.contentType}/${contentType?.contentSubtype}")
    
    val charset = message.charset()
    println("Charset: ${charset?.name}")
    
    val contentLength = message.contentLength()
    println("Content length: $contentLength bytes")
    
    // ETag handling
    val etag = message.etag()
    if (etag != null) {
        println("ETag: $etag")
        val isWeak = etag.startsWith("W/")
        val tagValue = etag.removePrefix("W/").trim('"')
        println("Weak ETag: $isWeak, Value: $tagValue")
    }
    
    // Vary header analysis
    val varyHeaders = message.vary()
    if (!varyHeaders.isNullOrEmpty()) {
        println("Varies by headers: ${varyHeaders.joinToString(", ")}")
    }
    
    // Cookie handling
    val cookies = message.setCookie()
    cookies.forEach { cookie ->
        println("Cookie: ${cookie.name}=${cookie.value}")
        println("  Domain: ${cookie.domain}")
        println("  Path: ${cookie.path}")
        println("  Secure: ${cookie.secure}")
        println("  HttpOnly: ${cookie.httpOnly}")
        if (cookie.maxAge > 0) {
            println("  Max-Age: ${cookie.maxAge} seconds")
        }
    }
    
    // Cache control analysis
    val cacheDirectives = message.cacheControl()
    cacheDirectives.forEach { directive ->
        println("Cache directive: ${directive.value}")
        directive.params.forEach { param ->
            println("  ${param.name}: ${param.value}")
        }
    }
}

Message Builder Convenience Extensions

Extension functions for setting common HTTP headers with validation.

/**
 * Set Max-Age cache control directive
 * @param seconds maximum age in seconds
 */
fun HttpMessageBuilder.maxAge(seconds: Int): Unit

/**
 * Set If-None-Match header for conditional requests
 * @param value ETag value to match against
 */
fun HttpMessageBuilder.ifNoneMatch(value: String): Unit

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

Usage Examples:

import io.ktor.http.*

// Building requests with convenience methods
fun buildApiRequest(): HttpMessage {
    return HttpMessageBuilder().apply {
        // Set common headers
        contentType(ContentType.Application.Json.withCharset(Charsets.UTF_8))
        userAgent("MyAPI-Client/2.1.0 (Android)")
        
        // Conditional request
        ifNoneMatch("\"v2.1-abc123\"")
        
        // Caching
        maxAge(300) // 5 minutes
        
        // Verify settings
        require(contentType()?.match(ContentType.Application.Json) == true)
        require(charset() == Charsets.UTF_8)
        require(etag() == null) // If-None-Match is for requests, ETag is for responses
    }.build()
}

// Building responses with cache control
fun buildCachedResponse(data: String, etag: String): HttpMessage {
    return HttpMessageBuilder().apply {
        contentType(ContentType.Text.Plain.withCharset(Charsets.UTF_8))
        headers.set(HttpHeaders.ETag, "\"$etag\"")
        maxAge(3600) // 1 hour
        headers.append(HttpHeaders.CacheControl, "public")
        headers.set(HttpHeaders.Vary, "Accept-Encoding, Accept-Language")
        
        // Add content
        headers.set(HttpHeaders.ContentLength, data.toByteArray().size.toString())
        
        // Verify response headers
        val parsedEtag = etag()
        val varyHeaders = vary()
        val cacheControl = cacheControl()
        
        println("ETag: $parsedEtag")
        println("Varies by: ${varyHeaders?.joinToString(", ")}")
        println("Cache directives: ${cacheControl.map { it.value }}")
    }.build()
}

Advanced Cookie Handling

import io.ktor.http.*

// Parse and analyze cookies from message
fun analyzeCookies(message: HttpMessage) {
    val cookies = message.setCookie()
    
    cookies.forEach { cookie ->
        println("Cookie Analysis:")
        println("  Name: ${cookie.name}")
        println("  Value: ${cookie.value}")
        println("  Encoding: ${cookie.encoding}")
        
        // Security attributes
        val securityLevel = when {
            cookie.secure && cookie.httpOnly -> "High (Secure + HttpOnly)"
            cookie.secure -> "Medium (Secure only)"
            cookie.httpOnly -> "Medium (HttpOnly only)"
            else -> "Low (No security flags)"
        }
        println("  Security: $securityLevel")
        
        // Expiration analysis
        when {
            cookie.maxAge > 0 -> {
                val hours = cookie.maxAge / 3600
                val days = hours / 24
                when {
                    days > 0 -> println("  Expires: in $days days")
                    hours > 0 -> println("  Expires: in $hours hours")
                    else -> println("  Expires: in ${cookie.maxAge} seconds")
                }
            }
            cookie.expires != null -> {
                println("  Expires: ${cookie.expires}")
            }
            else -> println("  Expires: Session cookie")
        }
        
        // Scope
        println("  Domain: ${cookie.domain ?: "current domain"}")
        println("  Path: ${cookie.path ?: "/"}")
        
        // Extensions
        if (cookie.extensions.isNotEmpty()) {
            println("  Extensions:")
            cookie.extensions.forEach { (key, value) ->
                println("    $key${if (value != null) "=$value" else ""}")
            }
        }
    }
}

// Content type handling with charset detection
fun handleContentType(message: HttpMessage): Pair<ContentType?, Charset?> {
    val contentType = message.contentType()
    val charset = message.charset()
    
    // Handle different content types
    when {
        contentType?.match(ContentType.Application.Json) == true -> {
            val effectiveCharset = charset ?: Charsets.UTF_8
            println("JSON content with charset: ${effectiveCharset.name}")
            return contentType to effectiveCharset
        }
        
        contentType?.match(ContentType.Text.Any) == true -> {
            val effectiveCharset = charset ?: Charsets.UTF_8
            println("Text content with charset: ${effectiveCharset.name}")
            return contentType to effectiveCharset
        }
        
        contentType?.match(ContentType.Application.OctetStream) == true -> {
            println("Binary content (no charset)")
            return contentType to null
        }
        
        contentType?.match(ContentType.MultiPart.Any) == true -> {
            println("Multipart content")
            // Extract boundary parameter
            val boundary = contentType.parameters.find { it.name == "boundary" }?.value
            println("Boundary: $boundary")
            return contentType to charset
        }
        
        else -> {
            println("Unknown or no content type")
            return null to null
        }
    }
}

Types

/**
 * HTTP message interface for reading headers and properties
 */
interface HttpMessage {
    val headers: Headers
}

/**
 * HTTP message builder interface for constructing messages
 */
interface HttpMessageBuilder {
    val headers: HeadersBuilder
}

/**
 * Header value with parameters (used by cache control parsing)
 */
data class HeaderValue(
    val value: String,
    val params: List<HeaderValueParam> = emptyList()
)

/**
 * Header value parameter
 */
data class HeaderValueParam(
    val name: String,
    val value: String
)

Install with Tessl CLI

npx tessl i tessl/kotlin-io-ktor--ktor-http-iosarm64

docs

authentication.md

content-processing.md

content-types.md

cookies.md

date-utilities.md

header-parsing.md

headers.md

http-message-extensions.md

http-methods-status.md

index.md

multipart.md

parameters.md

url-encoding.md

url-handling.md

tile.json