Bases de la spécification OpenAPI
La spécification OpenAPI (OAS) est un format standard pour décrire les API RESTful.
La spécification OpenAPI permet aux développeurs de définir la structure d'une API, ses paramètres, ses réponses et d'autres informations de manière lisible par machine.
La spécification OpenAPI s'appelait à l'origine la spécification Swagger ; elle a ensuite été donnée à l'OpenAPI Initiative et renommée OpenAPI.
Les principales fonctions de la spécification OpenAPI incluent :
- Fournir une documentation normalisée pour les API
- Prendre en charge les tests automatisés des API
- Générer des SDK clients
- Favoriser la séparation du développement frontend et backend
OpenAPI possède actuellement deux versions largement utilisées :
- OpenAPI 2.0 (anciennement Swagger 2.0)
- OpenAPI 3.x (dernière version stable)
Il est recommandé d'utiliser OpenAPI 3.x pour les nouveaux projets, car il offre davantage de fonctionnalités et d'améliorations.
Structure de la spécification OpenAPI
Les documents OpenAPI sont généralement écrits au format YAML ou JSON.
Voici une structure de document OpenAPI de base :
Exemple
info:
title: Example API # Nom de l'API
description: Ceci est un exemple de document d'API
version: 1.0.0 # Version de l'API
servers:
- url: https://api.example.com/v1 # Adresse du serveur d'API
description: Environnement de production
- url: https://dev-api.example.com/v1
description: Environnement de développement
paths: # Définitions des chemins d'API
/users: # Chemin du point de terminaison
get: # Méthode HTTP
summary: Récupérer tous les utilisateurs
description: Retourne une liste de tous les utilisateurs du système
operationId: getUsers
balises :
- users # Étiquette de groupe
parameters: # Paramètres de la requête
- name: limit
in: query
description: Limite du nombre de résultats renvoyés
schema:
type: integer
default: 20
responses: # Définitions des réponses
'200': # Code de statut HTTP
description: Renvoie avec succès la liste des utilisateurs
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
'400':
description: Paramètres de requête non valides
components: # Composants réutilisables
schemas: # Définitions du modèle de données
User:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
email:
type: string
format: email
required:
- id
- name
Explication détaillée des concepts fondamentaux d'OpenAPI
1. Métadonnées du document (info)
La section info contient des informations de base sur l'API, telles que title, description, version, etc. :
Exemple
title: API de gestion des utilisateurs
description: API pour gérer les informations utilisateur dans le système
version: 1.0.0
contact:
name: Équipe de support API
email: [email protected]
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
2. Informations sur les serveurs (servers)
La section servers définit la liste des serveurs API disponibles :
Exemple
- url: https://api.example.com/v1
description: Environnement de production
- url: https://staging-api.example.com/v1
description: Environnement de test
3. Chemins d'accès (paths)
La section paths définit tous les points de terminaison de l'API et les méthodes HTTP qu'ils prennent en charge :
Exemple
/users:
get:
# Obtenir la liste des utilisateurs
post:
# Créer un nouvel utilisateur
/users/{userId}:
get:
# Obtenir un utilisateur spécifique
put:
# Mettre à jour l'utilisateur
delete:
# Supprimer l'utilisateur
4. Opérations (operations)
Chaque méthode HTTP sous un chemin définit une opération d'API :
Exemple
/users/{userId}:
get:
summary: Obtenir les détails de l'utilisateur
description: Obtenir des informations détaillées sur l'utilisateur par ID utilisateur
operationId: getUserById
balises :
- users
parameters:
- name: userId
in: path
required: true
description: ID de l'utilisateur
schema:
type: integer
responses:
'200':
description: Récupération réussie des informations de l'utilisateur
content:
application/json:
schema:
$ref: '#/components/schemas/User'
'404':
description: L'utilisateur n'existe pas
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
5. Paramètres (parameters)
Les paramètres peuvent être définis à plusieurs emplacements :
Exemple
- name: userId
in: path # Paramètre de chemin
required: true
schema:
type: integer
- name: filter
in: query # Paramètre de requête
schema:
type: string
- name: X-API-Key
in: header # Paramètre d'en-tête
schema:
type: string
- name: trace
in: cookie # Paramètre de cookie
schema:
type: string
6. Corps de la requête (requestBody)
Définissez le corps de la requête pour les méthodes telles que POST, PUT, etc. :
Exemple
description: Données utilisateur
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/User'
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/UserForm'
7. Réponses (responses)
Définissez les réponses possibles pour chaque opération :
Exemple
'200':
description: Opération réussie
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
'400':
description: Paramètres de requête non valides
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
8. Composants (components)
La section components est utilisée pour stocker des éléments qui peuvent être réutilisés dans l'ensemble du document API :
Exemple
schemas:
User:
type: object
properties:
id:
type: integer
name:
type: string
email:
type: string
format: email
roles:
type: array
items:
type: string
enum: [admin, user, editor]
required:
- name
Error:
type: object
properties:
code:
type: integer
message:
type: string
required:
- code
- message
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
OAuth2:
type: oauth2
flows:
implicit:
authorizationUrl: https://example.com/oauth/authorize
scopes:
read: Autorisation de lecture
write: Autorisation d'écriture
9. Modèles de données (schémas)
Définissez les structures de données utilisées dans l'API:
Exemple
Product:
type: object
properties:
id:
type: integer
name:
type: string
maxLength: 100
price:
type: number
format: float
minimum: 0
category:
type: string
enum: [electronics, books, clothing]
10. Sécurité (security)
Définir les méthodes d'authentification et d'autorisation pour l'API :
Exemple
- ApiKeyAuth: []
- OAuth2: [read, write]
Créer un exemple complet de document OpenAPI
Voici un exemple plus complet d'API e-commerce :
Exemple
info:
title: API de commerce électronique
description: API de gestion des produits et des commandes dans une boutique en ligne
version: 1.0.0
contact:
name: Équipe de support API
email: [email protected]
url: https://api.example.com/support
license:
name: MIT
url: https://opensource.org/licenses/MIT
servers:
- url: https://api.example.com/v1
description: Environnement de production
- url: https://dev-api.example.com/v1
description: Environnement de développement
balises :
- name: products
description: Opérations liées aux produits
- name: orders
description: Opérations liées aux commandes
- name: users
description: Opérations liées aux utilisateurs
paths:
/products:
get:
summary: Obtenir la liste des produits
description: Renvoie une liste de tous les produits disponibles, avec prise en charge de la pagination et du filtrage
operationId: getProducts
balises :
- products
parameters:
- name: category
in: query
description: Filtrer par catégorie de produit
schema:
type: string
- name: page
in: query
description: Numéro de page
schema:
type: integer
default: 1
- name: limit
in: query
description: Nombre d'éléments par page
schema:
type: integer
default: 20
responses:
'200':
description: Liste de produits récupérée avec succès
content:
application/json:
schema:
type: object
properties:
total:
type: integer
products:
type: array
items:
$ref: '#/components/schemas/Product'
'400':
description: Erreur de paramètre
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
summary: Créer un nouveau produit
description: Créer les informations du nouveau produit
operationId: createProduct
balises :
- products
security:
- ApiKeyAuth: []
- OAuth2: [write]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProductCreate'
responses:
'201':
description: Produit créé avec succès
content:
application/json:
schema:
$ref: '#/components/schemas/Product'
'400':
description: Données de requête non valides
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Non autorisé
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/products/{productId}:
get:
summary: Obtenir les détails du produit
description: Obtenir des informations détaillées sur un produit spécifique par ID
operationId: getProductById
balises :
- products
parameters:
- name: productId
in: path
required: true
description: ID du produit
schema:
type: integer
responses:
'200':
description: Informations sur le produit récupérées avec succès
content:
application/json:
schema:
$ref: '#/components/schemas/Product'
'404':
description: Produit introuvable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
summary: Mettre à jour le produit
description: Mettre à jour les informations d'un produit spécifique
operationId: updateProduct
balises :
- products
security:
- ApiKeyAuth: []
- OAuth2: [write]
parameters:
- name: productId
in: path
required: true
description: ID du produit
schema:
type: integer
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProductUpdate'
responses:
'200':
description: Produit mis à jour avec succès
content:
application/json:
schema:
$ref: '#/components/schemas/Product'
'400':
description: Données de requête non valides
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Non autorisé
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Produit introuvable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
summary: Supprimer le produit
description: Supprimer un produit spécifique
operationId: deleteProduct
balises :
- products
security:
- ApiKeyAuth: []
- OAuth2: [write]
parameters:
- name: productId
in: path
required: true
description: ID du produit
schema:
type: integer
responses:
'204':
description: Produit supprimé avec succès
'401':
description: Non autorisé
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Produit introuvable
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/orders:
get:
summary: Obtenir la liste des commandes
description: Renvoie une liste de toutes les commandes, avec prise en charge de la pagination et du filtrage
operationId: getOrders
balises :
- orders
security:
- ApiKeyAuth: []
- OAuth2: [read]
parameters:
- name: status
in: query
description: Filtrer par statut de commande
schema:
type: string
enum: [pending, processing, shipped, delivered, cancelled]
- name: page
in: query
description: Numéro de page
schema:
type: integer
default: 1
- name: limit
in: query
description: Nombre d'éléments par page
schema:
type: integer
default: 20
responses:
'200':
description: Liste des commandes récupérée avec succès
content:
application/json:
schema:
type: object
properties:
total:
type: integer
orders:
type: array
items:
$ref: '#/components/schemas/Order'
'401':
description: Non autorisé
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
post:
summary: Créer une nouvelle commande
description: Créer une nouvelle commande
operationId: createOrder
balises :
- orders
security:
- ApiKeyAuth: []
- OAuth2: [write]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OrderCreate'
responses:
'201':
description: Commande créée avec succès
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'400':
description: Données de requête non valides
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'401':
description: Non autorisé
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
components:
schemas:
Product:
type: object
properties:
id:
type: integer
format: int64
readOnly: true
name:
type: string
maxLength: 100
description :
type: string
price:
type: number
format: float
minimum: 0
category:
type: string
enum: [electronics, books, clothing, food]
inStock:
type: boolean
default: true
createdAt:
type: string
format: date-time
readOnly: true
updatedAt:
type: string
format: date-time
readOnly: true
required:
- name
- price
- category
ProductCreate:
type: object
properties:
name:
type: string
maxLength: 100
description :
type: string
price:
type: number
format: float
minimum: 0
category:
type: string
enum: [electronics, books, clothing, food]
inStock:
type: boolean
default: true
required:
- name
- price
- category
ProductUpdate:
type: object
properties:
name:
type: string
maxLength: 100
description :
type: string
price:
type: number
format: float
minimum: 0
category:
type: string
enum: [electronics, books, clothing, food]
inStock:
type: boolean
Order:
type: object
properties:
id:
type: integer
format: int64
readOnly: true
userId:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
totalAmount:
type: number
format: float
readOnly: true
status:
type: string
enum: [pending, processing, shipped, delivered, cancelled]
default: pending
shippingAddress:
$ref: '#/components/schemas/Address'
createdAt:
type: string
format: date-time
readOnly: true
updatedAt:
type: string
format: date-time
readOnly: true
required:
- userId
- items
- shippingAddress
OrderCreate:
type: object
properties:
userId:
type: integer
format: int64
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
shippingAddress:
$ref: '#/components/schemas/Address'
required:
- userId
- items
- shippingAddress
OrderItem:
type: object
properties:
productId:
type: integer
format: int64
quantity:
type: integer
minimum: 1
default: 1
unitPrice:
type: number
format: float
readOnly: true
required:
- productId
- quantity
Adresse :
type: object
properties:
street:
type: string
city:
type: string
état :
type: string
zipCode:
type: string
country:
type: string
required:
- street
- city
- state
- zipCode
- country
Error:
type: object
properties:
code:
type: integer
message:
type: string
required:
- code
- message
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
OAuth2:
type: oauth2
flows:
implicit:
authorizationUrl: https://example.com/oauth/authorize
scopes:
read: Autorisation de lecture
write: Autorisation d'écriture
security:
- ApiKeyAuth: []
Syntaxe de base de la spécification OpenAPI
La spécification OpenAPI prend en charge deux formats :
- YAML (recommandé)
- JSON
Exemple de format YAML
Exemple
info:
title: API de l'animalerie
version: 1.0.0
paths:
/pets:
get:
summary: Lister tous les animaux
responses:
'200':
description: Liste des animaux récupérée avec succès
Exemple de format JSON
Exemple
"info": {
"title": "API Animalerie",
"version": "1.0.0"
},
"paths": {
"/pets": {
"get": {
"summary": "Lister tous les animaux",
"responses": {
"200": {
"description": "Liste des animaux récupérée avec succès"
}
}
}
}
}
}
Comment utiliser la spécification OpenAPI
1. Créer et modifier des documents OpenAPI
Vous pouvez utiliser les outils suivants pour créer et modifier des documents OpenAPI :
- Swagger Editor: éditeur en ligne avec aperçu et validation en temps réel
- Stoplight Studio: outil de conception visuelle d'API
- VS Code + extension OpenAPI: modifier dans un environnement de développement intégré
2. Génération de documents
La spécification OpenAPI peut générer automatiquement une belle documentation d'API. Les outils courants incluent :
- Swagger UI: générer une documentation d'API interactive
- ReDoc: fournit une documentation réactive et personnalisable
- Slate: générer une documentation statique élégante
3. Génération de code
OpenAPI peut générer automatiquement du code client et serveur dans plusieurs langages :
- OpenAPI Generator: prend en charge 40+ langages de programmation
- Swagger Codegen: générer du code client et serveur
- NSwag: Générateur de code pour l’écosystème .NET
4. Tests et simulation d’API
La spécification OpenAPI peut aussi être utilisée pour :
- Tests automatisés: Utilisation d’outils tels que Postman, SoapUI
- Simulation d’API: Prism, Microcks, etc. peuvent simuler des API en se basant sur la spécification OpenAPI
Bonnes pratiques
1. Principes de conception
- Conserver une cohérence dans le nommage des endpoints
- Utiliser les méthodes HTTP et les codes de statut appropriés
- Concevoir une structure de chemin d’URL claire
2. Recommandations de documentation
- Fournir des descriptions et des exemples détaillés
- Utiliser des tags pour regrouper les API
- Spécifier clairement les paramètres requis
3. Stratégie de gestion des versions
- Inclure le numéro de version dans l'URL (
/v1/users) - Utiliser les en-têtes de requête pour spécifier la version (
Accept: application/vnd.example.v1+json) - Spécifier clairement les informations de version dans le document OpenAPI
Questions fréquentes
1. Quelle est la différence entre OpenAPI et Swagger ?
Swagger est le prédécesseur de la spécification OpenAPI. En 2016, la spécification Swagger a été donnée à la Linux Foundation et renommée en spécification OpenAPI. Aujourd'hui, « Swagger » désigne généralement l'ensemble d'outils construit autour de la spécification OpenAPI.
2. Quelles sont les principales différences entre OpenAPI 2.0 et 3.x ?
OpenAPI 3.x a introduit de nombreuses nouvelles fonctionnalités, notamment :
- Meilleure réutilisation des composants
- Définitions de corps de requête plus flexibles
- Définitions de sécurité plus puissantes
- Prise en charge améliorée de JSON Schema
- Prise en charge des liens et des callbacks
3. Comment gérer l'authentification et l'autorisation ?
OpenAPI prend en charge plusieurs mécanismes de sécurité :
- Clés d'API
- Authentification de base HTTP
- OAuth2.0
- OpenID Connect
- Authentification par en-tête personnalisé
Ressources d'apprentissage
- Documentation officielle :OpenAPI Initiative
- Outils :
- Ressources d'apprentissage :