Progression Partie 5 sur 12

Créer et configurer le client HTTP

Les dépendances Ktor sont maintenant disponibles dans notre projet, mais nous ne pouvons pas encore effectuer de requête.

Nous devons d’abord créer un HttpClient. Il sera responsable de préparer et d’envoyer les requêtes HTTP, de recevoir les réponses du serveur, de détecter les erreurs HTTP et de convertir les réponses JSON en objets Kotlin.

Nous créerons un seul client et le réutiliserons pour toutes les requêtes envoyées à REST Countries.

Dans le package data, crée un fichier nommé HttpClient.kt

Créer le client avec le moteur Android

Voici à quoi va ressembler la declaration de la variable :

data/HttpClient.kt
...
import io.ktor.client.HttpClient
import io.ktor.client.engine.android.Android

val httpClient = HttpClient(Android) {

}

Transformer les erreurs HTTP en exceptions

À l’intérieur du bloc HttpClient, ajoute la ligne suivante :

expectSuccess = true

Le code doit maintenant ressembler à ceci :

data/HttpClient.kt
val httpClient = HttpClient(Android) {
    expectSuccess = true
}

Une réponse HTTP contient un code indiquant le résultat de la requête.

Voici quelques exemples :

200 → la requête a réussi

401 → la clé d’API est absente ou invalide

404 → la ressource demandée n’existe pas

500 → une erreur est survenue sur le serveur

Avec expectSuccess = true, Ktor considère automatiquement les réponses qui ne représentent pas un succès comme des erreurs.

Nous pourrons ensuite intercepter ces exceptions et afficher un message approprié dans l’interface.

Installer ContentNegotiation

Toujours à l’intérieur du bloc HttpClient, sous expectSuccess, ajoute le plugin ContentNegotiation :

data/HttpClient.kt
...
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.serialization.kotlinx.json.json
...
val httpClient = HttpClient(Android) {
    expectSuccess = true

    install(ContentNegotiation) {
        json()
    }
}

ContentNegotiation indique à Ktor comment traiter le contenu reçu. Dans notre cas, il permettra au client de reconnaître que la réponse contient du JSON et de la convertir en objets Kotlin.

Configurer la lecture du JSON

Nous voulons maintenant personnaliser le comportement de kotlinx.serialization.

Dans l’appel json(), remplace :

KOTLIN
json()

par :

data/HttpClient.kt
...
import kotlinx.serialization.json.Json
...
json(
    Json {
        ignoreUnknownKeys = true
        isLenient = true
    }
)

La configuration complète du plugin devient :

data/HttpClient.kt
install(ContentNegotiation) {
    json(
        Json {
            ignoreUnknownKeys = true
            isLenient = true
        }
    )
}

ignoreUnknownKeys = true permet d’ignorer les propriétés retournées par l’API que nous n’avons pas déclarées dans nos classes Kotlin.

isLenient = true rend le parseur un peu plus permissif lorsqu’il lit du JSON.

Dans notre cas, REST Countries retourne normalement du JSON valide. Cette option permet néanmoins au client de tolérer certaines variations mineures dans le format reçu.

Vérifier le fichier final

À ce stade, le fichier HttpClient.kt doit contenir :

data/HttpClient.kt
package com.composechef.countryexplorer.data

import io.ktor.client.HttpClient
import io.ktor.client.engine.android.Android
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json

val httpClient = HttpClient(Android) {
    expectSuccess = true

    install(ContentNegotiation) {
        json(
            Json {
                ignoreUnknownKeys = true
                isLenient = true
            }
        )
    }
}

Notre client HTTP est maintenant prêt à envoyer des requêtes et à convertir les réponses JSON.

Dans la prochaine partie, nous allons déclarer les classes Kotlin qui correspondent à la structure de la réponse retournée par REST Countries.