Une API de données a une mission fondamentale : recevoir des requêtes de machines clientes, exécuter un calcul ou une interrogation, et renvoyer une réponse propre au format JSON.
Dans cette leçon, nous allons dépasser le classique "Hello World" pour construire un premier micro-service analytique capable d'ingérer des paramètres et de renvoyer des indicateurs calculés.
🌐 Les Deux Méthodes HTTP Clés pour la Data : GET et POST#
En tant qu'analyste de données ou ingénieur MLOps, vous utiliserez quasi-exclusivement deux verbes du protocole HTTP :
┌────────────────────────────────────────────────────────┐
│ 1. MÉTHODE GET : Demander des Données Existantes │
│ Client ──► "Donne-moi les ventes du magasin Paris" │
│ ──► Paramètres visibles dans l'URL (?region=Paris) │
│ ──► Utilisé pour : /health, /metrics, /reports │
└────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────┐
│ 2. MÉTHODE POST : Envoyer des Données pour Traitement │
│ Client ──► "Voici les caractéristiques d'un client... │
│ calcule-moi sa probabilité de churn !" │
│ ──► Données transmises dans le corps (Body JSON) │
│ ──► Utilisé pour : /predict, /train, /batch-score │
└────────────────────────────────────────────────────────┘
🏗️ Anatomie d'un Micro-Service Analytique#
Créez un fichier nommé app.py et observez la mise en place de ces deux méthodes :
from flask import Flask, jsonify, request
app = Flask(__name__)
# 1. Endpoint de santé système (Health Check)
@app.route("/api/v1/health", methods=["GET"])
def health_check():
"""Vérifie que l'API est active et prête à recevoir du trafic."""
return jsonify({
"status": "healthy",
"service": "Analytics & Scoring Engine",
"version": "1.0.0"
}), 200
# 2. Endpoint avec paramètre d'URL dynamique (Filtrage)
@app.route("/api/v1/kpis/<region>", methods=["GET"])
def get_regional_kpis(region):
"""Renvoie les indicateurs clés pour une région géographique spécifique."""
# Simulation d'un filtre sur un DataFrame
kpi_db = {
"europe": {"chiffre_affaires": 850000, "croissance": 0.14, "clients_actifs": 1240},
"amerique": {"chiffre_affaires": 1250000, "croissance": 0.22, "clients_actifs": 2100},
"afrique": {"chiffre_affaires": 420000, "croissance": 0.35, "clients_actifs": 890}
}
result = kpi_db.get(region.lower())
if not result:
return jsonify({"erreur": f"La région '{region}' est introuvable."}), 404
return jsonify({"region": region.capitalize(), "kpis": result}), 200
# 3. Endpoint POST recevant un payload JSON (Préparation au scoring)
@app.route("/api/v1/simulate-basket", methods=["POST"])
def simulate_basket():
"""Reçoit une liste d'articles et calcule le montant TTC et la remise."""
payload = request.get_json()
# Validation minimale de l'entrée
if not payload or "articles" not in payload:
return jsonify({"erreur": "Payload JSON invalide. Clé 'articles' requise."}), 400
articles = payload["articles"]
total_ht = sum(item.get("prix", 0) * item.get("quantite", 1) for item in articles)
# Règle métier : 10% de remise si le panier dépasse 100 €
remise = total_ht * 0.10 if total_ht > 100 else 0.0
total_ttc = (total_ht - remise) * 1.20 # TVA 20%
return jsonify({
"nb_articles": len(articles),
"total_ht": round(total_ht, 2),
"remise_appliquee": round(remise, 2),
"total_ttc": round(total_ttc, 2)
}), 200
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)
🚀 Lancer et Tester l'Application#
1. Démarrer le serveur#
Dans votre terminal (avec l'environnement virtuel actif) :
* Serving Flask app 'app'
* Debug mode: on
* Running on all addresses (0.0.0.0)
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
* Restarting with stat
* Debugger is active!
2. Tester les requêtes avec Python (requests)#
Ouvrez un second terminal ou un notebook Python pour simuler les appels d'un client externe :
import requests
BASE_URL = "http://127.0.0.1:5000/api/v1"
# Test 1 : Health Check (GET)
res_health = requests.get(f"{BASE_URL}/health")
print("Health Check :", res_health.json())
# Test 2 : KPIs Régionaux (GET avec paramètre)
res_kpis = requests.get(f"{BASE_URL}/kpis/europe")
print("KPIs Europe :", res_kpis.json())
# Test 3 : Simulation de panier (POST avec payload JSON)
mon_panier = {
"articles": [
{"nom": "Écran 27 pouces", "prix": 180.0, "quantite": 1},
{"nom": "Câble HDMI", "prix": 15.0, "quantite": 2}
]
}
res_basket = requests.post(f"{BASE_URL}/simulate-basket", json=mon_panier)
print("Simulation :", res_basket.json())
Exécutez ce script de test :
Health Check : {'service': 'Analytics & Scoring Engine', 'status': 'healthy', 'version': '1.0.0'}
KPIs Europe : {'kpis': {'chiffre_affaires': 850000, 'clients_actifs': 1240, 'croissance': 0.14}, 'region': 'Europe'}
Simulation : {'nb_articles': 2, 'remise_appliquee': 21.0, 'total_ht': 210.0, 'total_ttc': 226.8}
⚠️ Les Codes d'État HTTP à Respecter Impérativement#
Une API professionnelle ne renvoie pas un simple message textuel en cas de pépin : elle utilise les codes de statut HTTP normés pour avertir le client :
200 OK: Le calcul a réussi, la réponse est dans le JSON.201 Created: Une nouvelle ressource a été enregistrée avec succès.400 Bad Request: Le JSON envoyé par le client est malformé ou il manque une variable prédictive obligatoire.404 Not Found: La route demandée ou l'identifiant n'existe pas.500 Internal Server Error: Une exception Python non gérée a crashé sur le serveur (à éviter absolument grâce à des blocstry...except).
Vous maîtrisez désormais les flux de données entrants et sortants dans Flask. Cependant, placer l'intégralité de son code dans un seul fichier app.py devient ingérable dès que le projet grandit. Dans la prochaine leçon, nous allons structurer notre projet selon les standards de l'industrie.
Commentaires