Ktor é um cliente HTTP assíncrono e um framework de servidor para Kotlin que suporta desenvolvimento multiplataforma. A biblioteca é construída sobre corrotinas Kotlin e funciona em JVM, iOS, Android, JS e Native. De acordo com o repositório do Ktor no GitHub, o projeto é ativamente desenvolvido pela equipe JetBrains. Ktor oferece uma arquitetura modular com um sistema de plugins para configuração flexível de conexões HTTP.
Principais pontos
Ktor é um framework para criar clientes e servidores HTTP em Kotlin, desenvolvido pela JetBrains. Ao contrário das bibliotecas tradicionais, o Ktor foi projetado desde o início para desenvolvimento multiplataforma e funciona em todas as plataformas suportadas pelo Kotlin.
Ktor usa uma abordagem de middleware, inspirada na arquitetura do Kodein e Express.js. Cada requisição passa por um pipeline de funções handler que podem modificar a requisição e a resposta. Isso oferece flexibilidade indisponível em bibliotecas com arquitetura rígida baseada em anotações.
A versão atual Ktor 3.0 inclui suporte para Kotlin 2.0, o compilador K2 e um novo motor CIO (Coroutine I/O) com desempenho melhorado. A biblioteca é distribuída sob a licença Apache 2.0 e está disponível para uso comercial sem restrições.
O lado do cliente do Ktor é totalmente construído sobre corrotinas Kotlin, fornecendo execução assíncrona eficiente de requisições sem bloqueio de threads. O lado do servidor permite criar servidores HTTP com roteamento, processamento de requisições e conexões WebSocket.
Ktor usa uma arquitetura de plugins: todos os recursos adicionais — logging, serialização, autenticação — são conectados através de plugins. Isso torna a biblioteca modular e permite conectar apenas os componentes necessários, reduzindo o tamanho da aplicação final.
Graças a uma API unificada em todas as plataformas, o desenvolvedor não precisa aprender diferentes clientes HTTP para iOS e Android. Em um projeto multiplataforma, o código da camada de rede é totalmente compartilhado, e a implementação específica da plataforma fica oculta atrás do motor HttpClient. Isso reduz o tempo de desenvolvimento e diminui o número de erros relacionados às diferenças entre plataformas.
Ktor fornece um conjunto de recursos que o tornam uma escolha atraente para projetos Kotlin modernos, especialmente os multiplataforma.
Ktor funciona em JVM, Android, iOS, macOS, Windows, Linux, JavaScript e Wasm. O mesmo código de cliente HTTP é executado em todas as plataformas sem alterações. Esta é uma vantagem chave sobre bibliotecas vinculadas ao OkHttp ou URLSession.
As corrotinas Kotlin fornecem assincronicidade natural sem callbacks. Cada requisição é uma função suspend que pode ser chamada de qualquer corrotina. Ktor suporta streaming de respostas via Flow, o que é conveniente para conexões longas e WebSocket.
Os plugins do Ktor são conectados através de um bloco install e configurados separadamente. Plugins principais: ContentNegotiation para serialização, Logging para logging, Auth para autenticação e WebSockets para comunicação bidirecional. Cada plugin pode ser ativado ou desativado independentemente.
O tratamento de erros no Ktor é baseado em exceções. A classe ClientRequestException é lançada para códigos 4xx, ServerResponseException para 5xx e IOException para falhas de rede. Os timeouts são configurados através do plugin HttpTimeout, que define o tempo de espera para conexão, leitura e escrita. Para tentativas de repetição, o plugin Retry é usado com configurações de número de tentativas e atraso.
Ktor usa uma arquitetura de pipeline onde cada requisição passa por uma cadeia de handlers. O cliente cria uma configuração HttpClient com plugins instalados, e cada chamada a get ou post passa pelos plugins na ordem em que foram conectados.
O objeto HttpClient é criado com um motor específico da plataforma: CIO para JVM e Android, Darwin para iOS e macOS, OkHttp para compatibilidade Android, Js para navegador. O motor pode ser selecionado explicitamente ou deixado para escolha automática. Cada requisição retorna um HttpResponse contendo o corpo da resposta, cabeçalhos e status.
val client = HttpClient(CIO) {
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
})
}
}
suspend fun fetchUsers(): List<User> {
return client.get("https://api.example.com/users").body()
}
A instalação do Ktor é feita via Gradle ou Maven. Para projetos multiplataforma, as dependências são especificadas em sourceSets para cada destino. Ktor é distribuído através do Maven Central.
Em build.gradle.kts, adicione a dependência ktor-client-core para o código comum e um motor para a plataforma específica. A versão do Ktor é definida através de uma variável em gradle.properties. Ktor 3.x requer Kotlin 2.0+ e suporta o compilador K2.
val ktorVersion = "3.0.3"
dependencies {
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-cio:$ktorVersion")
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
implementation("io.ktor:ktor-client-logging:$ktorVersion")
}
Para iOS, é usado o motor Darwin, que encapsula o URLSession nativo. No Kotlin Multiplatform, isso proporciona desempenho máximo e integração com os mecanismos de cache do sistema iOS. O motor é adicionado como uma dependência separada no sourceSet iOS.
Uma característica importante do Ktor é o suporte a diferentes formatos de serialização através do ContentNegotiation. Além de JSON, o plugin suporta Protobuf, CBOR, XML e formatos personalizados. Para serialização, são usadas as bibliotecas kotlinx.serialization ou Jackson, e o desenvolvedor pode alternar entre elas sem alterar o código das requisições.
Os exemplos abaixo demonstram cenários típicos de trabalho com o cliente Ktor: uma requisição GET básica, envio de dados e trabalho com código multiplataforma.
Uma requisição GET simples com desserialização automática da resposta em uma data class. Ktor usa o plugin ContentNegotiation com kotlinx.serialization para converter JSON em objetos. O código é conciso e type-safe.
@Serializable
data class Post(
val id: Int,
val title: String,
val body: String
)
suspend fun getPosts(): List<Post> {
val response = client.get("https://jsonplaceholder.typicode.com/posts")
return response.body()
}
Uma requisição POST no Ktor envia uma data class como corpo JSON através do método post com contentType e setBody. O plugin ContentNegotiation serializa automaticamente o objeto em uma string JSON. A resposta pode ser processada de forma síncrona ou assíncrona.
suspend fun createPost(): Post {
val newPost = Post(
id = 0,
title = "Nova publicação",
body = "Conteúdo da publicação"
)
val response = client.post("https://jsonplaceholder.typicode.com/posts") {
contentType(ContentType.Application.Json)
setBody(newPost)
}
return response.body()
}
O método submitFormWithBinaryData no Ktor permite enviar arquivos e formulários em formato multipart. Ktor divide automaticamente os dados em partes e adiciona cabeçalhos. Para acompanhar o progresso, é usado onUpload, que recebe os bytes de dados enviados.
suspend fun uploadFile(fileBytes: ByteArray) {
client.submitFormWithBinaryData(
url = "https://api.example.com/upload",
formData = formData {
append("file", fileBytes, Headers.build {
append(HttpHeaders.ContentType, "image/png")
append(HttpHeaders.ContentDisposition, "filename=\"photo.png\"")
})
}
)
}
A escolha entre Ktor e Retrofit depende da arquitetura do projeto e dos requisitos de multiplataforma. Retrofit continua sendo o padrão para projetos somente Android, enquanto o Ktor é a melhor escolha para Kotlin Multiplatform.
Ktor também fornece suporte integrado para WebSocket e SSE (Server-Sent Events), tornando-o conveniente para aplicações em tempo real. Retrofit não suporta WebSocket diretamente — é necessária uma biblioteca OkHttp WebSocket separada. Ktor também é mais fácil de configurar para diferentes ambientes graças ao seu sistema de plugins, onde cada plugin é responsável por uma função.
O plugin Auth no Ktor suporta autenticação básica, tokens Bearer, Digest e OAuth2. A configuração de autenticação é feita declarativamente: o desenvolvedor especifica o provedor, a fonte do token e o escopo. Ktor adiciona automaticamente cabeçalhos de autenticação às requisições e pode renovar o token quando ele expirar.
Se um projeto usa Kotlin Multiplatform com código compartilhado em iOS e Android, Ktor é a única opção que funciona em ambas as plataformas sem camadas adicionais. Retrofit está fortemente vinculado ao OkHttp e JVM, tornando-o inadequado para iOS.
Para projetos somente Android, Retrofit oferece uma API mais madura, um número maior de conversores e interceptadores OkHttp. Ktor também funciona neste cenário, mas seu ecossistema de plugins é menos extenso. Ambas as bibliotecas suportam corrotinas e oferecem desempenho comparável.
| Critério | Ktor | Retrofit |
|---|---|---|
| Multiplataforma | iOS, Android, JVM, JS, Native | Apenas JVM e Android |
| Motor HTTP | CIO, Darwin, OkHttp, Js | OkHttp |
| Conversores | kotlinx.serialization, Jackson | Gson, Moshi, Jackson, Protobuf |
| Arquitetura | Pipeline com plugins | Anotações com geração de código |
| Desenvolvedor | JetBrains | Square |
Perguntas frequentes
Ktor — um cliente HTTP multiplataforma sobre corrotinas da JetBrains. Retrofit — uma biblioteca Android da Square baseada em OkHttp. Ktor funciona em iOS, Android, JS e Native, enquanto o Retrofit funciona apenas em JVM.
Sim, Ktor suporta iOS através do motor Darwin, que usa URLSession nativo. Isso garante desempenho máximo e funcionamento correto com o cache do sistema iOS. O código do cliente permanece compartilhado entre as plataformas.
Ktor suporta os motores: CIO (JVM/Android), Darwin (iOS/macOS), OkHttp (Android), Js (navegador), Jetty, Netty, Tomcat (servidor). O motor pode ser selecionado explicitamente ou deixado para seleção automática padrão.
Sim, Ktor tem suporte integrado para WebSocket tanto no cliente quanto no servidor. Para o cliente, é usado o plugin WebSockets, que permite estabelecer uma conexão bidirecional e trocar mensagens em tempo real.
Os erros são tratados via try-catch em torno das chamadas suspend. Ktor lança ClientRequestException para 4xx, ServerResponseException para 5xx e IOException para erros de rede. Recomenda-se usar o tipo Result para unificação.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também