Skip to Content
Mélodium 0.10.3 is now available!
DocsExemples05. Client HTTP

Client HTTP

Source: tutorial/05_http_client See in Playground

Récupère un article depuis une API publique de test (jsonplaceholder.typicode.com), re-sérialise son corps JSON, et l’écrit dans un fichier.

Exécution

cd tutorial/05_http_client melodium run Compo.toml --post_id 1

L’URL de la requête est construite à partir de post_id avec |format. L’exemple journalise la fin de la requête, et distingue séparément un échec technique (DNS, connexion, dépassement de délai) d’un corps qui échoue à l’analyse, avant d’écrire le corps JSON analysé puis re-sérialisé dans post.txt.

Optionnel : ajoutez --api-report et un jeton d’API (MELODIUM_API_TOKEN) pour voir la trace complète de cette exécution sur Cadence.CI.

Fonctionnement

Cet exemple n’utilise aucun modèle : get n’a besoin d’aucun modèle de client pour une requête ponctuelle. Un modèle HttpClient à connexion réutilisable est employé à la place dans d’autres exemples, dès qu’une connexion doit rester ouverte entre plusieurs requêtes.

Flux de données

Déclenchement de la requête

get(url=...) se déclenche sur startup.trigger et diffuse le corps de la réponse via data, indépendamment de status/completed/failed/error, qui se déclenchent chacun une seule fois. L’URL est construite avec |format, appelée directement comme une valeur, sans port ni connexion :

fetch: get(url=|format("https://jsonplaceholder.typicode.com/posts/{id}", |map([|entry("id", post_id)]))) startup.trigger -> fetch.trigger logOk: logInfoMessage(label="http", message="request completed") fetch.completed -> logOk.trigger

Échec technique et échec applicatif

fetch.failed/fetch.error se déclenchent quand la requête elle-même n’a pas pu aboutir : problème de DNS, de connexion, ou de délai dépassé. Une réponse qui arrive avec succès mais dont le contenu n’est pas du JSON valide relève d’un tout autre mode d’échec, traité plus loin lorsque l’Option de toJson revient à none. Les deux ne doivent pas être confondus :

netFailed: logErrorMessage(label="http", message="request failed technically") netError: logError(label="http") fetch.failed -> netFailed.trigger fetch.error -> netError.message

Décodage et re-sérialisation du corps

Le corps brut, en octets, est transformé en Stream<string> avec decode, analysé avec toJson, extrait avec unwrapOr, puis re-sérialisé. Cet aller-retour est un bon moyen de confirmer qu’une réponse est bien du JSON valide sans en changer le sens :

decode: decode() fetch.data -> decode.data parsed: toJson() body: unwrapOr<Json>(default=|null()) asText: toString<Json>() write: writeTextLocal(path=output) logDone: logInfoMessage(label="http", message="response written to file") decode.text -> parsed.text,json -> body.option,value -> asText.value,into -> write.text write.finished -> logDone.trigger

Dépendances

[dependencies] std = "0.10.3" # flux de base, journalisation, structures de données http = "0.10.3" # client et serveur HTTP json = "0.10.3" # analyse et sérialisation JSON encoding = "0.10.3" # encodage/décodage UTF-8 fs = "0.10.3" # lecture/écriture de fichiers locaux