HTTP клиент на Kotlin: делаем запросы правильно от А до Я

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

HTTP клиент на Kotlin: делаем запросы правильно от А до Я

Современная разработка на Kotlin немыслима без взаимодействия с удалёнными серверами. Будь то мобильное приложение на Android или серверное решение на Ktor — HTTP-запросы являются основой обмена данными. В этой статье мы разберём, как создавать HTTP-клиенты на Kotlin, используя лучшие практики, популярные библиотеки и современный подход с корутинами. Вы узнаете, как делать GET и POST запросы, обрабатывать ошибки, работать с JSON и строить надёжную архитектуру сетевого слоя.

Почему Kotlin идеален для HTTP-клиентов?

Kotlin предлагает лаконичный синтаксис, нулевую безопасность (null safety) и полную совместимость с Java-экосистемой. Благодаря корутинам (coroutines) асинхронные запросы становятся интуитивно понятными, без громоздких колбэков. Вы можете писать последовательный код, который выполняется асинхронно — это значительно упрощает чтение и отладку. Кроме того, Kotlin активно используется в Android-разработке, где сетевые запросы — повседневная задача.

Основные библиотеки для HTTP в Kotlin

На сегодняшний день наиболее популярны три подхода:

  • Ktor Client — мультиплатформенный клиент от JetBrains. Поддерживает JVM, Android, iOS, JS и Native. Идеален для проектов, где нужна единая кодовая база.
  • OkHttp + Retrofit — классический стек для Android/JVM. OkHttp отвечает за низкоуровневую работу с сетью, а Retrofit генерирует типизированные интерфейсы.
  • Fuel — лёгкая библиотека с функциональным подходом. Подходит для небольших проектов.

В этой статье мы сосредоточимся на Ktor и OkHttp, так как они покрывают 90% сценариев.

Настройка проекта и первые запросы

Для начала добавим зависимости. Если вы используете Gradle (Kotlin DSL), подключите Ktor Client:

dependencies {
    implementation("io.ktor:ktor-client-core:2.3.7")
    implementation("io.ktor:ktor-client-cio:2.3.7") // движок CIO
    implementation("io.ktor:ktor-client-content-negotiation:2.3.7")
    implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.7")
}

Для OkHttp зависимости будут такими:

dependencies {
    implementation("com.squareup.okhttp3:okhttp:4.12.0")
    implementation("com.squareup.okhttp3:logging-interceptor:4.12.0")
    implementation("com.google.code.gson:gson:2.10.1")
}

GET-запрос с Ktor Client

Создадим простой клиент и выполним GET-запрос к публичному API:

import io.ktor.client.*
import io.ktor.client.request.*
import io.ktor.client.statement.*

suspend fun fetchData(): String {
    val client = HttpClient()
    val response: HttpResponse = client.get("https://jsonplaceholder.typicode.com/posts/1")
    val body = response.bodyAsText()
    client.close()
    return body
}

// Использование в корутине
fun main() = runBlocking {
    println(fetchData())
}

Обратите внимание: suspend — ключевое слово Kotlin для приостанавливаемых функций. Это позволяет выполнять запрос без блокировки потока.

GET-запрос с OkHttp

Аналогичный пример на OkHttp выглядит так:

import okhttp3.OkHttpClient
import okhttp3.Request

fun fetchDataSync(): String {
    val client = OkHttpClient()
    val request = Request.Builder()
        .url("https://jsonplaceholder.typicode.com/posts/1")
        .build()
    client.newCall(request).execute().use { response ->
        return response.body?.string() ?: "Ошибка"
    }
}

// Вызов в обычном потоке (блокирующий)
fun main() {
    println(fetchDataSync())
}

OkHttp по умолчанию синхронный, но его легко адаптировать под корутины с помощью suspendCancellableCoroutine.

POST-запросы и работа с JSON

Отправка данных — вторая важнейшая операция. Рассмотрим, как отправить JSON-объект на сервер.

POST с Ktor и сериализацией

Ktor отлично интегрируется с kotlinx.serialization. Сначала определим data-класс:

@Serializable
data class Post(val userId: Int, val id: Int? = null, val title: String, val body: String)

Теперь выполним POST:

import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.http.*

suspend fun createPost(): Post {
    val client = HttpClient {
        install(ContentNegotiation) {
            json()
        }
    }
    val newPost = Post(userId = 1, title = "Kotlin", body = "HTTP client")
    val response = client.post("https://jsonplaceholder.typicode.com/posts") {
        contentType(ContentType.Application.Json)
        setBody(newPost)
    }
    return response.body()
}

POST с OkHttp и Gson

Для OkHttp потребуется вручную сериализовать объект:

import com.google.gson.Gson
import okhttp3.*

fun createPostSync(): String {
    val client = OkHttpClient()
    val gson = Gson()
    val post = Post(userId = 1, title = "Kotlin", body = "HTTP client")
    val json = gson.toJson(post)

    val requestBody = json.toRequestBody("application/json; charset=utf-8".toMediaType())
    val request = Request.Builder()
        .url("https://jsonplaceholder.typicode.com/posts")
        .post(requestBody)
        .build()

    client.newCall(request).execute().use { response ->
        return response.body?.string() ?: "Ошибка"
    }
}

Обработка ошибок и таймауты

Сеть нестабильна, поэтому обработка ошибок обязательна. Рассмотрим типовые сценарии.

Ktor: обработка исключений

Ktor выбрасывает исключения при сетевых ошибках. Используйте try-catch:

suspend fun safeFetch(): String {
    return try {
        val client = HttpClient()
        val response = client.get("https://example.com/api")
        response.bodyAsText()
    } catch (e: Exception) {
        "Ошибка: ${e.message}"
    } finally {
        client.close()
    }
}

Также можно настроить таймауты:

val client = HttpClient {                

Блоги

Рекомендаций по книгам