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 :

  1. OpenAPI 2.0 (anciennement Swagger 2.0)
  2. 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

openapi: 3.1.0 # Version d'OpenAPI
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

info:
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

servers:
  - 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

paths:
  /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

paths:
  /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

parameters:
  - 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

requestBody:
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

responses:
  '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

components:
  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
        - email
   
    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

schemas:
  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

security:
  - ApiKeyAuth: []
  - OAuth2: [read, write]

Créer un exemple complet de document OpenAPI

Voici un exemple plus complet d'API e-commerce :

Exemple

openapi: 3.1.0
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 :

  1. YAML (recommandé)
  2. JSON

Exemple de format YAML

Exemple

openapi: 3.0.0
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

"openapi": "3.0.0",
  "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

  1. Documentation officielle :OpenAPI Initiative
  2. Outils :
  3. Ressources d'apprentissage :
Autres extensions