Aller au contenu
English

OpenAPI et Swagger UI

  • Leçon 10
  • 40 min
  • Module 4 : Documenter l'API avec OpenAPI et Swagger UI

Ce que vous saurez faire

Utilisez la documentation que votre API possède déjà : un contrat lisible par machine et une page interactive. Chacun peut y essayer chaque point de terminaison. Vérifiez ensuite qu’elle correspond au comportement réel de l’API. Une documentation incorrecte est pire qu’une absence de documentation.

Avant de commencerCe qu’il faut savoir et avoir sous la mainEnviron 40 minutes

Ce que vous devez savoir

Ce qu’il vous faut sur votre ordinateur

Testé avec FastAPI 0.142.2 (OpenAPI 3.1) et Chrome 141 sur macOS.

Dans le module 3, vous avez écrit le contrat sous forme de tableau pour les gens. OpenAPI est un format standard pour ce même contrat, en JSON (ou YAML), destiné aux programmes. Un document OpenAPI liste chaque chemin et méthode, les paramètres, le corps de requête et chaque réponse avec son code d’état. Il liste aussi le schéma de chaque corps : ses champs, ses types et ses limites.

Vous n’en avez pas écrit, mais votre API en possède un. FastAPI construit le document à partir de votre code, chaque fois que l’application démarre :

  • les routes donnent les chemins, les méthodes et les codes d’état,
  • les modèles Pydantic donnent les schémas,
  • les arguments de FastAPI(...) donnent le titre et la version.

Comme plusieurs outils lisent le même format, un seul document les alimente tous :

Votre code comprend les métadonnées de l'application, les modèles et les routes. FastAPI l'utilise pour générer openapi.json, le document OpenAPI. Quatre outils le lisent : Swagger UI à /docs pour lire et essayer des requêtes, ReDoc à /redoc pour lire, Postman pour l'importer comme collection, et des tests qui le comparent au contrat révisé.
Un seul document, généré à partir du code, alimente les pages de documentation, Postman et les tests.
Description textuelle du diagramme

Les métadonnées de l’application (titre, version, étiquettes), les modèles (champs, limites, exemples) et les routes (méthodes, chemins, résumés) constituent votre code. FastAPI génère openapi.json à partir de ces éléments. Swagger UI à /docs l’affiche et vous permet d’essayer des requêtes. ReDoc à /redoc l’affiche pour la lecture. Postman peut l’importer comme collection (module 5). Des tests peuvent le comparer à une copie révisée du contrat (leçon 3 de ce module).

Le document se trouve à /openapi.json. Amira l’enregistre dans un fichier pour le lire dans VS Code :

Terminal (on Windows: curl.exe)
curl -o openapi.json http://127.0.0.1:8000/openapi.json

Il tient sur une seule longue ligne. Dans VS Code, ouvrez-le et utilisez Format Document (mettre en forme le document) pour le rendre lisible. Le raccourci est Shift+Alt+F, ou Shift+Option+F sur macOS. Voici la partie pour POST /v1/classify, abrégée :

openapi.json (part)
"/v1/classify": {
"post": {
"tags": ["tickets"],
"summary": "Classify",
"requestBody": {
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/TicketIn"}}},
"required": true
},
"responses": {
"200": {"description": "Successful Response",
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/Classification"}}}},
"422": {"description": "Validation Error",
"content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}
}
}
}

$ref signifie « le schéma est défini ailleurs dans ce document », sous components (composants). Voici TicketIn :

openapi.json (components.schemas.TicketIn)
"TicketIn": {
"type": "object",
"properties": {
"subject": {"type": "string", "maxLength": 120, "minLength": 1, "title": "Subject"},
"body": {"type": "string", "maxLength": 5000, "title": "Body", "default": ""}
},
"required": ["subject"],
"additionalProperties": false
}

Chaque règle de votre modèle s’y trouve : minLength et maxLength viennent de Field(...). required (obligatoire) est présent parce que subject n’a aucune valeur par défaut. additionalProperties: false vient de extra="forbid". Vous avez écrit les règles une seule fois, en Python. Le document, la validation et la documentation proviennent tous de cette même source.

Swagger UI est une page Web qui présente un document OpenAPI sous forme de documentation interactive. FastAPI la sert à /docs. Ouvrez http://127.0.0.1:8000/docs :

Swagger UI pour Ticket Classifier API, version 0.1.0, OAS 3.1, avec un lien vers /openapi.json. La section tickets contient GET /v1/categories List Categories (lister les catégories) et POST /v1/classify Classify (classifier). La section default (par défaut) contient GET /health Health (état de santé). En dessous, une section Schemas (schémas) liste CategoryList, Classification, HTTPValidationError, TicketIn et ValidationError.
Swagger UI regroupe les points de terminaison par étiquette. Les routes avec tags=['tickets'] sont ensemble; /health n'a aucune étiquette et se trouve donc sous default (par défaut). L’image est en anglais.

Sélectionnez POST /v1/classify pour l’ouvrir :

Le point de terminaison POST /v1/classify ouvert. Request body (corps de requête), required (obligatoire), application/json, avec l'exemple subject valant string et body vide. Responses (réponses) : 200 Successful Response (réponse réussie) avec l'exemple category valant billing, priority valant 1, confidence valant 1, model_version valant string. 422 Validation Error (erreur de validation) avec un exemple de liste detail contenant loc, msg, type, input et ctx.
Chaque point de terminaison affiche son corps de requête et chaque réponse documentée, avec un exemple construit à partir du schéma. L’image est en anglais.

Pour envoyer une vraie requête, sélectionnez Try it out (essayer). Le corps d’exemple devient une zone de texte modifiable. Sélectionnez Execute (exécuter) :

Après Execute (exécuter) : une commande curl pour POST http://127.0.0.1:8000/v1/classify avec le corps JSON, l'URL de requête et la réponse du serveur : code 200, corps de réponse avec category valant billing, priority valant 1, confidence valant 0.9, model_version valant keywords-1.0, et les en-têtes de réponse.
Swagger UI affiche la commande curl équivalente, le corps de réponse réel et les en-têtes de réponse. L’image est en anglais.

Swagger UI envoie une vraie requête de votre navigateur à votre API. Il affiche aussi cette même requête sous forme de commande curl. C’est une façon rapide de construire une commande pour le terminal ou pour un rapport de bogue. (La commande curl utilise les guillemets '...' pour le corps. Sous Windows, utilisez plutôt un fichier de corps, comme dans le module 1.)

FastAPI sert aussi ReDoc à /redoc. C’est le même document, présenté sur une longue page, avec les points de terminaison à gauche et les schémas au centre. Il n’offre pas de bouton Try it out. Les équipes utilisent souvent Swagger UI pendant le développement, et ReDoc comme page de référence pour les utilisateurs de l’API. Les deux lisent le même openapi.json : ils ne peuvent donc jamais se contredire. Ils peuvent toutefois contredire le code, comme vous le verrez ensuite.

Exemple détaillé : la documentation dit-elle la vérité?

Section intitulée « Exemple détaillé : la documentation dit-elle la vérité? »

Amira compare la documentation avec son tableau de contrat du module 3. Elle essaie {"subject": ""} dans Swagger UI :

La documentation dit L’API répond réellement
Corps 422 {"detail": [{"loc": [...], "msg": "...", "type": "...", "input": "...", "ctx": {}}]} {"error": {"code": "invalid_request", "message": "...", "fields": ["subject"]}}

La documentation est incorrecte. FastAPI ajoute le schéma 422 standard (HTTPValidationError) à chaque point de terminaison qui possède un corps. Mais dans le module 3, Amira a remplacé la réponse réelle par sa propre structure. Un développeur d’interface qui se fie à /docs écrit du code pour detail (détails). Ce code échoue dès le premier billet de soutien invalide.

Elle trouve d’autres lacunes :

  1. 404, 405 et 500 ne sont pas documentés, et ils utilisent tous la structure error (erreur).
  2. Les résumés proviennent des noms de fonctions : Classify (classifier), List Categories (lister les catégories). Rien ne dit ce que fait le point de terminaison.
  3. Le corps d’exemple est {"subject": "string", "body": ""}. Envoyé tel quel, il renvoie other (autre), ce qui n’enseigne rien.
  4. Rien n’explique priority (priorité : 1 indique-t-il la plus urgente ou la moins urgente?) ni confidence (confiance).
  5. /health se trouve sous default (par défaut), seul dans son groupe, et n’a aucune description.

Aucun de ces problèmes n’est un bogue de l’API. Ce sont des bogues de documentation, et la prochaine leçon les corrige.

  1. Ouvrez http://127.0.0.1:8000/docs. Vérifiez que vous voyez les trois points de terminaison et les schémas.
  2. Ouvrez GET /v1/categories, sélectionnez Try it out, puis Execute. Le corps de réponse liste les cinq catégories, avec le code 200.
  3. Ouvrez POST /v1/classify, sélectionnez Try it out, mettez le sujet Charged twice for March (facturé deux fois pour mars) dans le corps, puis sélectionnez Execute. Copiez la commande curl et exécutez-la dans un terminal (sous Windows, modifiez-la pour utiliser un fichier de corps). Vous obtenez le même résultat.
  4. Remplacez le corps par {"subject": ""} et exécutez la requête. Comparez le corps de réponse avec l’exemple 422 sous Responses (réponses). Ils ne correspondent pas.
  5. Ouvrez http://127.0.0.1:8000/redoc. Trouvez le schéma de Classification et comparez-le avec la section Schemas (schémas) de Swagger UI.
  6. Enregistrez le document avec curl -o openapi.json http://127.0.0.1:8000/openapi.json, mettez-le en forme dans VS Code et trouvez additionalProperties.

À vous de jouer : réviser la documentation sans connaître l’API

Section intitulée « À vous de jouer : réviser la documentation sans connaître l’API »

Imaginez que vous développez une interface et devez créer une page qui envoie des billets à cette API. Vous avez seulement /docs. Notez trois questions auxquelles la documentation ne répond pas. Pour chacune, indiquez où la réponse devrait aller dans le code : la route, un champ de modèle ou l’application.

Afficher quelques réponses
  • « Que signifie la priorité 1? » → une description du champ priority dans Classification.
  • « Que dois-je montrer à l’utilisateur quand je reçois une erreur? » → les réponses d’erreur, documentées avec ErrorResponse, sur la route.
  • « Quelles catégories existent, et de nouvelles peuvent-elles apparaître? » → une description de category (catégorie) et la description de l’application.
  • « Le champ body est-il obligatoire? » → visible dans le schéma (required liste seulement subject), mais une description de body (corps) le précise.
  • « Y a-t-il une limite pour le sujet? » → visible dans le schéma (maxLength: 120), mais pas dans l’exemple.
  • « Ai-je besoin d’une clé? » → pas encore. Le module 6 en ajoute une, et la documentation doit l’indiquer.

Erreur courante

/docs affiche une page vide

Symptôme : http://127.0.0.1:8000/docs affiche une page blanche ou seulement le titre de l’onglet. /openapi.json fonctionne.

Cause : la page Swagger UI charge son JavaScript et ses styles depuis un CDN public (cdn.jsdelivr.net). Sans connexion Internet, ou sur un réseau qui bloque ce site, la page n’a aucun code à exécuter. ReDoc à /redoc dépend du même service. L’API elle-même fonctionne bien.

Solution :

  1. Ouvrez les onglets Console (console) et Network (réseau) des outils de développement. Les requêtes échouées vers cdn.jsdelivr.net confirment la cause.
  2. Connectez-vous à Internet ou essayez un autre réseau.
  3. Sans Internet, lisez directement /openapi.json ou importez-le dans Postman (prochain module), qui n’a pas besoin du CDN.

Vérifiez votre compréhension

Vous changez max_length de subject de 120 à 200 dans TicketIn. Que devez-vous changer dans la documentation?

Afficher la réponse

Rien à la main. FastAPI génère le document OpenAPI à partir du modèle lorsque l’application démarre. Ainsi, maxLength devient 200 dans /openapi.json, dans Swagger UI et dans ReDoc en même temps. C’est le principal avantage de la documentation générée : les règles se trouvent à un seul endroit.

Vérifiez votre compréhension

Si la documentation est générée à partir du code, comment peut-elle être incorrecte?

Afficher la réponse

Elle connaît seulement ce que le code indique à FastAPI. Les gestionnaires d’erreurs changent la vraie réponse 422, mais la route ne l’indique pas. FastAPI documente donc sa propre structure par défaut. Il ne peut pas non plus connaître ce que vous avez seulement en tête, comme la signification de priority 1. La documentation générée décrit toute la structure, mais vous devez ajouter le sens et les exceptions.

Récapitulatif

  • OpenAPI est un contrat standard lisible par machine : chemins, méthodes, paramètres, corps, réponses et schémas.
  • FastAPI le génère à /openapi.json à partir de vos routes, de vos modèles et des paramètres de l’application.
  • Swagger UI (/docs) l’affiche et envoie de vraies requêtes avec Try it out. ReDoc (/redoc) l’affiche pour la lecture.
  • La documentation générée peut quand même être incorrecte : ici, la structure 422. Comparez-la toujours avec les vraies réponses.

Ensuite, vous corrigez chaque lacune : les descriptions, les exemples et les réponses d’erreur telles qu’elles sont réellement.

Leçon suivante : Une documentation utilisable