or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

authentication.mdcontent-processing.mdcontent-types.mdcookies.mddate-utilities.mdheader-parsing.mdheaders.mdhttp-message-extensions.mdhttp-methods-status.mdindex.mdmultipart.mdparameters.mdurl-encoding.mdurl-handling.md
tile.json

content-processing.mddocs/

Content Processing

Outgoing content abstractions for different content types including streaming, byte arrays, protocol upgrades, and comprehensive content handling utilities.

Capabilities

Outgoing Content Base Class

Base sealed class for all outgoing HTTP content types with common properties and extension support.

/**
 * Base class for all outgoing HTTP content
 */
sealed class OutgoingContent {
    /** Content type of the outgoing content */
    abstract val contentType: ContentType?
    
    /** Content length in bytes if known */
    abstract val contentLength: Long?
    
    /** HTTP status code to send with content */
    abstract val status: HttpStatusCode?
    
    /** Additional headers to send with content */
    abstract val headers: Headers
    
    /**
     * Get extension property by key
     * @param key attribute key
     * @return property value or null
     */
    fun <T : Any> getProperty(key: AttributeKey<T>): T?
    
    /**
     * Set extension property
     * @param key attribute key
     * @param value property value
     */
    fun <T : Any> setProperty(key: AttributeKey<T>, value: T?)
    
    /**
     * Get trailing headers (HTTP/2 trailers)
     * @return trailing headers or null
     */
    open fun trailers(): Headers? = null
}

Content Type Implementations

Specific implementations for different content delivery patterns.

/**
 * Content without payload (e.g., 204 No Content)
 */
object NoContent : OutgoingContent()

/**
 * Content read from ByteReadChannel (streaming)
 */
abstract class ReadChannelContent : OutgoingContent() {
    /**
     * Get content channel for reading
     * @return ByteReadChannel with content data
     */
    abstract fun readFrom(): ByteReadChannel
    
    /**
     * Get content channel for specific byte range
     * @param range byte range to read
     * @return ByteReadChannel with range data
     */
    open fun readFrom(range: LongRange): ByteReadChannel = readFrom()
}

/**
 * Content written to ByteWriteChannel
 */
abstract class WriteChannelContent : OutgoingContent() {
    /**
     * Write content to output channel
     * @param channel output channel to write to
     */
    abstract suspend fun writeTo(channel: ByteWriteChannel)
}

/**
 * Content as byte array (in-memory)
 */
abstract class ByteArrayContent : OutgoingContent() {
    /**
     * Get content as byte array
     * @return content bytes
     */
    abstract fun bytes(): ByteArray
}

/**
 * Protocol upgrade content (e.g., WebSocket upgrade)
 */
abstract class ProtocolUpgrade : OutgoingContent() {
    /** Always returns SwitchingProtocols status */
    final override val status: HttpStatusCode get() = HttpStatusCode.SwitchingProtocols
    
    /**
     * Upgrade connection protocol
     * @param input input channel
     * @param output output channel  
     * @param engineContext engine coroutine context
     * @param userContext user coroutine context
     * @return Job managing the upgraded connection
     */
    abstract suspend fun upgrade(
        input: ByteReadChannel,
        output: ByteWriteChannel,
        engineContext: CoroutineContext,
        userContext: CoroutineContext
    ): Job
}

Null Body Representation

Special object representing absent content body.

/**
 * Represents null/absent body content
 */
object NullBody

Usage Examples:

import io.ktor.http.content.*
import io.ktor.http.*

// Create content with no payload
val noContent = object : OutgoingContent.NoContent() {
    override val contentType = null
    override val contentLength = 0L
    override val status = HttpStatusCode.NoContent
    override val headers = headersOf()
}

// Create byte array content
val jsonContent = object : OutgoingContent.ByteArrayContent() {
    private val data = """{"message": "Hello World"}""".toByteArray(Charsets.UTF_8)
    
    override val contentType = ContentType.Application.Json
    override val contentLength = data.size.toLong()
    override val headers = headersOf()
    override val status = HttpStatusCode.OK
    
    override fun bytes(): ByteArray = data
}

// Create streaming content
val streamingContent = object : OutgoingContent.WriteChannelContent() {
    override val contentType = ContentType.Text.Plain
    override val contentLength = null // Unknown length
    override val headers = headersOf()
    override val status = HttpStatusCode.OK
    
    override suspend fun writeTo(channel: ByteWriteChannel) {
        repeat(100) { i ->
            channel.writeStringUtf8("Line $i\n")
            delay(10) // Simulate streaming delay
        }
        channel.close()
    }
}

// Set extension properties
jsonContent.setProperty(AttributeKey("custom-info"), "Generated content")
val customInfo = jsonContent.getProperty(AttributeKey<String>("custom-info"))

// Check content properties
println("Content type: ${jsonContent.contentType}")
println("Content length: ${jsonContent.contentLength}")
println("Status: ${jsonContent.status}")
println("Has headers: ${!jsonContent.headers.isEmpty()}")

// Work with protocol upgrade (conceptual example)
val webSocketUpgrade = object : OutgoingContent.ProtocolUpgrade() {
    override val contentType = null
    override val contentLength = null
    override val headers = headersOf(
        HttpHeaders.Upgrade to "websocket",
        HttpHeaders.Connection to "Upgrade"
    )
    
    override suspend fun upgrade(
        input: ByteReadChannel,
        output: ByteWriteChannel,
        engineContext: CoroutineContext,
        userContext: CoroutineContext
    ): Job {
        // Implement WebSocket protocol handling
        return Job()
    }
}

Types

/**
 * Attribute key for extension properties
 */
class AttributeKey<T : Any>(val name: String)

/**
 * Coroutine context for async operations
 * (Provided by Kotlin coroutines library)
 */
// CoroutineContext is from kotlin.coroutines

/**
 * Job for managing coroutine lifecycle
 * (Provided by Kotlin coroutines library) 
 */
// Job is from kotlinx.coroutines

/**
 * Byte channels for streaming I/O
 * (Provided by Ktor I/O library)
 */
// ByteReadChannel and ByteWriteChannel are from io.ktor.utils.io