Ktor HTTP Client Core for tvOS ARM64 - multiplatform asynchronous HTTP client library with coroutines support
—
The response handling API provides comprehensive functionality for accessing response data, headers, status information, and converting response bodies to various types with streaming support.
abstract class HttpResponse : HttpMessage, CoroutineScope {
public abstract val call: HttpClientCall
public abstract val status: HttpStatusCode
public abstract val version: HttpProtocolVersion
public abstract val requestTime: GMTDate
public abstract val responseTime: GMTDate
override fun toString(): String
}
class HttpStatement(
private val builder: HttpRequestBuilder,
internal val client: HttpClient
) {
suspend fun execute(): HttpResponse
suspend fun <T> execute(block: suspend (response: HttpResponse) -> T): T
suspend inline fun <reified T> body(): T
}
// Extension properties and functions for HttpResponse
val HttpResponse.request: HttpRequest
// Response body reading extensions
suspend fun HttpResponse.bodyAsText(fallbackCharset: Charset = Charsets.UTF_8): String
suspend fun HttpResponse.bodyAsChannel(): ByteReadChannel
suspend fun HttpResponse.bodyAsBytes(): ByteArrayval response = client.get("https://api.example.com/users")
println("Status: ${response.status}") // Status: 200 OK
println("Status code: ${response.status.value}") // Status code: 200
println("Status description: ${response.status.description}") // Status description: OK
// Status checks
if (response.status.isSuccess()) {
println("Request succeeded")
}
when (response.status.value) {
200 -> println("OK")
404 -> println("Not Found")
500 -> println("Server Error")
}val response = client.get("https://api.example.com/users")
// Individual headers
val contentType = response.headers["Content-Type"]
val contentLength = response.headers["Content-Length"]?.toLongOrNull()
val server = response.headers["Server"]
// All headers
response.headers.forEach { name, values ->
println("$name: ${values.joinToString(", ")}")
}
// Typed header access
val etag = response.headers[HttpHeaders.ETag]
val lastModified = response.headers[HttpHeaders.LastModified]val response = client.get("https://api.example.com/users")
println("Request time: ${response.requestTime}")
println("Response time: ${response.responseTime}")
val duration = response.responseTime.timestamp - response.requestTime.timestamp
println("Request took: ${duration}ms")val response = client.get("https://api.example.com/users")
println("HTTP version: ${response.version}") // HTTP/1.1, HTTP/2.0, etc.suspend fun HttpResponse.bodyAsText(
charset: Charset = Charsets.UTF_8
): String
suspend fun HttpResponse.bodyAsText(
fallbackCharset: Charset = Charsets.UTF_8
): Stringval response = client.get("https://api.example.com/users")
val text = response.bodyAsText()
println(text)
// With specific charset
val textUtf8 = response.bodyAsText(Charsets.UTF_8)suspend fun HttpResponse.bodyAsBytes(): ByteArrayval response = client.get("https://api.example.com/image.jpg")
val bytes = response.bodyAsBytes()
File("downloaded-image.jpg").writeBytes(bytes)fun HttpResponse.bodyAsChannel(): ByteReadChannelval response = client.get("https://api.example.com/large-file")
val channel = response.bodyAsChannel()
// Stream processing
while (!channel.isClosedForRead) {
val packet = channel.readRemaining(8192)
// Process packet
}With appropriate serialization plugins (like kotlinx.serialization):
@Serializable
data class User(val id: Int, val name: String, val email: String)
val response = client.get("https://api.example.com/users/123")
val user = response.body<User>()
println("User: ${user.name}")val response = client.get("https://api.example.com/large-dataset")
val channel = response.bodyAsChannel()
val outputFile = File("dataset.json")
outputFile.outputStream().use { output ->
while (!channel.isClosedForRead) {
val packet = channel.readRemaining(8192)
output.write(packet.readBytes())
}
}With the BodyProgress plugin:
client.get("https://api.example.com/large-file") {
onDownload { bytesSentTotal, contentLength ->
val progress = (bytesSentTotal * 100 / contentLength).toInt()
println("Download progress: $progress%")
}
}.bodyAsBytes()val statement = client.prepareGet("https://api.example.com/users")
val response = statement.execute()
val text = response.bodyAsText()val statement = client.prepareGet("https://api.example.com/users")
val users = statement.execute { response ->
if (response.status.isSuccess()) {
response.bodyAsText()
} else {
throw RuntimeException("Request failed: ${response.status}")
}
}val userStatement = client.prepareGet {
url("https://api.example.com/users")
header("Authorization", "Bearer $token")
}
// Use multiple times
val page1 = userStatement.execute {
parameter("page", 1)
bodyAsText()
}
val page2 = userStatement.execute {
parameter("page", 2)
bodyAsText()
}val response = client.get("https://api.example.com/users/999")
when {
response.status.isSuccess() -> {
val user = response.bodyAsText()
println("User: $user")
}
response.status.value == 404 -> {
println("User not found")
}
response.status.value in 400..499 -> {
val errorBody = response.bodyAsText()
println("Client error: $errorBody")
}
response.status.value in 500..599 -> {
println("Server error: ${response.status}")
}
}client.get("https://api.example.com/users") {
// With HttpCallValidator plugin, non-success responses throw exceptions
}val response = client.get("https://api.example.com/users")
val contentType = response.headers[HttpHeaders.ContentType]
if (contentType?.startsWith("application/json") == true) {
val json = response.bodyAsText()
// Process JSON
} else {
println("Unexpected content type: $contentType")
}val response = client.get("https://api.example.com/file")
val contentLength = response.headers[HttpHeaders.ContentLength]?.toLongOrNull()
val actualBytes = response.bodyAsBytes()
if (contentLength != null && actualBytes.size.toLong() != contentLength) {
println("Content length mismatch!")
}val response = client.get("https://api.example.com/users")
val cacheControl = response.headers[HttpHeaders.CacheControl]
val etag = response.headers[HttpHeaders.ETag]
val expires = response.headers[HttpHeaders.Expires]
val lastModified = response.headers[HttpHeaders.LastModified]
println("Cache Control: $cacheControl")
println("ETag: $etag")// Using If-None-Match with ETag
val etag = "W/\"abc123\""
val response = client.get("https://api.example.com/users") {
header(HttpHeaders.IfNoneMatch, etag)
}
if (response.status.value == 304) {
println("Content not modified")
} else {
val newContent = response.bodyAsText()
val newEtag = response.headers[HttpHeaders.ETag]
}val response = client.get("https://api.example.com/users")
// Access coroutine context
val job = response.coroutineContext[Job]
val dispatcher = response.coroutineContext[CoroutineDispatcher]
// Use response as coroutine scope
response.launch {
// Background processing of response
}val response = client.get("https://api.example.com/users")
println("Request URL: ${response.call.request.url}")
println("Request method: ${response.call.request.method}")
println("Response status: ${response.call.response.status}")Install with Tessl CLI
npx tessl i tessl/maven-io-ktor--ktor-client-core-tvosarm64