Logo REST API

REST API

L'architecture REpresentational State Transfer qui définit des standards pour la communication entre systèmes web avec des interfaces simples, évolutives et fiables.

Pour les non-initiés

Qu'est-ce qu'une REST API ?

Imaginez que vous allez au restaurant. Vous avez un menu (une liste de ressources disponibles), vous passez une commande (vous faites une requête), et le serveur vous apporte votre plat (la réponse). Vous n'avez pas besoin de savoir comment fonctionne la cuisine ou comment le plat est préparé.

Une API REST fonctionne de manière similaire. C'est une interface qui permet à différents systèmes informatiques de communiquer entre eux sur internet de manière standardisée, sans avoir à connaître les détails techniques de l'autre système.

Pourquoi les API REST sont importantes ?

Universalité

Elles permettent à des applications écrites dans des langages différents et sur des plateformes différentes de communiquer facilement.

Simplicité

Elles utilisent des standards web simples (HTTP, JSON) que la plupart des développeurs connaissent déjà.

En résumé, les API REST sont comme un langage commun qui permet à différentes applications de partager des informations et des fonctionnalités, ce qui est essentiel pour l'écosystème moderne d'applications web, mobiles et de services cloud interconnectés.

Pour les développeurs

Fonctionnement technique

REST (Representational State Transfer) est un style d'architecture pour les systèmes distribués, défini par Roy Fielding dans sa thèse de doctorat en 2000. Une API RESTful s'appuie sur le protocole HTTP et ses méthodes pour exposer des ressources via des URLs standardisées, souvent utilisée avec Icône Node.jsNode.js ou d'autres langages back-end.

Les principes fondamentaux

Architecture client-serveur sans état

Chaque requête du client au serveur doit contenir toutes les informations nécessaires pour la comprendre et y répondre. Le serveur ne conserve pas d'état de session entre les requêtes.

  • Pas de session côté serveur
  • Chaque requête est indépendante
  • Nécessite généralement une authentification à chaque requête (JWT, API keys, etc.)

Opérations CRUD via les méthodes HTTP

Les API REST utilisent les méthodes HTTP standard pour effectuer les opérations CRUD (Create, Read, Update, Delete) sur les ressources.

  • GET : Lecture de ressources
  • POST : Création de ressources
  • PUT : Mise à jour complète d'une ressource
  • PATCH : Mise à jour partielle d'une ressource
  • DELETE : Suppression d'une ressource
Endpoints REST
// Exemples d'endpoints REST pour une ressource "products" // Récupérer la liste des produits GET /api/products // Récupérer un produit spécifique GET /api/products/42 // Créer un nouveau produit POST /api/products Content-Type: application/json { "name": "Écouteurs sans fil Pro", "description": "Écouteurs avec réduction active du bruit", "price": 199.99, "category_id": 8 } // Mettre à jour un produit (complètement) PUT /api/products/42 Content-Type: application/json { "name": "Écouteurs sans fil Pro+", "description": "Écouteurs premium avec réduction active du bruit", "price": 249.99, "category_id": 8 } // Mettre à jour partiellement un produit PATCH /api/products/42 Content-Type: application/json { "price": 229.99 } // Supprimer un produit DELETE /api/products/42 // Récupérer les avis sur un produit (relation imbriquée) GET /api/products/42/reviews // Filtrer et paginer les résultats GET /api/products?category=8&min_price=100&max_price=300&page=2&limit=20 // Trier les résultats GET /api/products?sort=price_desc

Représentation des ressources

Les ressources sont représentées dans un format standard, généralement JSON ou XML. Le format JSON est aujourd'hui le plus utilisé pour sa légèreté et sa compatibilité avec Icône JavaScriptJavaScript.

Représentation JSON d'une ressource
// Réponse JSON d'une API REST pour une requête GET /api/products/42 { "id": 42, "name": "Smartphone Galaxy X10", "description": "Dernier modèle avec écran pliable et appareil photo 108MP", "price": 999.99, "currency": "EUR", "stock": 157, "category": { "id": 8, "name": "Électronique" }, "tags": ["smartphone", "android", "premium"], "rating": 4.7, "created_at": "2023-05-12T10:30:00Z", "updated_at": "2023-09-28T14:15:22Z", "_links": { "self": { "href": "/api/products/42" }, "category": { "href": "/api/categories/8" }, "reviews": { "href": "/api/products/42/reviews" } } }

Utilisation des codes HTTP

Les API REST utilisent les codes de statut HTTP pour indiquer le résultat d'une opération.

  • 2xx : Succès (200 OK, 201 Created, 204 No Content)
  • 4xx : Erreur client (400 Bad Request, 401 Unauthorized, 404 Not Found)
  • 5xx : Erreur serveur (500 Internal Server Error, 503 Service Unavailable)

Implémentation avec Icône Node.jsNode.js

Voici un exemple d'implémentation d'une API REST avec Icône Node.jsNode.js et Express, illustrant les bonnes pratiques:

API REST avec Node.js et Express
// Exemple de REST API avec Node.js et Express const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app.use(bodyParser.json()); // Base de données simulée let products = [ { id: 1, name: 'Smartphone Galaxy X10', price: 999.99, category: 'Électronique' }, { id: 2, name: 'Laptop Pro 15"', price: 1299.99, category: 'Informatique' } ]; // GET - Récupérer tous les produits app.get('/api/products', (req, res) => { // Filtrage let result = [...products]; if (req.query.category) { result = result.filter(p => p.category === req.query.category); } if (req.query.min_price) { result = result.filter(p => p.price >= parseFloat(req.query.min_price)); } // Pagination const page = parseInt(req.query.page) || 1; const limit = parseInt(req.query.limit) || 10; const startIndex = (page - 1) * limit; // Ajouter des métadonnées de pagination const totalItems = result.length; const paginatedResult = { data: result.slice(startIndex, startIndex + limit), meta: { total: totalItems, page: page, limit: limit, total_pages: Math.ceil(totalItems / limit) }, _links: { self: `/api/products?page=${page}&limit=${limit}`, first: '/api/products?page=1&limit=' + limit, last: `/api/products?page=${Math.ceil(totalItems / limit)}&limit=${limit}` } }; // Ajouter next et prev si nécessaire if (page > 1) { paginatedResult._links.prev = `/api/products?page=${page - 1}&limit=${limit}`; } if (page < Math.ceil(totalItems / limit)) { paginatedResult._links.next = `/api/products?page=${page + 1}&limit=${limit}`; } res.json(paginatedResult); }); // GET - Récupérer un produit par son ID app.get('/api/products/:id', (req, res) => { const product = products.find(p => p.id === parseInt(req.params.id)); if (!product) { return res.status(404).json({ error: 'Produit non trouvé' }); } // Ajouter des liens HATEOAS const productWithLinks = { ...product, _links: { self: `/api/products/${product.id}`, collection: '/api/products' } }; res.json(productWithLinks); }); // POST - Créer un nouveau produit app.post('/api/products', (req, res) => { const { name, price, category } = req.body; // Validation basique if (!name || !price) { return res.status(400).json({ error: 'Le nom et le prix sont requis' }); } const newProduct = { id: products.length + 1, name, price, category: category || 'Non catégorisé' }; products.push(newProduct); // Statut 201 Created avec l'en-tête Location res.status(201) .location(`/api/products/${newProduct.id}`) .json(newProduct); }); // PUT - Mettre à jour un produit app.put('/api/products/:id', (req, res) => { const productIndex = products.findIndex(p => p.id === parseInt(req.params.id)); if (productIndex === -1) { return res.status(404).json({ error: 'Produit non trouvé' }); } const { name, price, category } = req.body; // Validation if (!name || !price) { return res.status(400).json({ error: 'Le nom et le prix sont requis' }); } // Mise à jour complète products[productIndex] = { id: parseInt(req.params.id), name, price, category: category || 'Non catégorisé' }; res.json(products[productIndex]); }); // DELETE - Supprimer un produit app.delete('/api/products/:id', (req, res) => { const productIndex = products.findIndex(p => p.id === parseInt(req.params.id)); if (productIndex === -1) { return res.status(404).json({ error: 'Produit non trouvé' }); } products.splice(productIndex, 1); // Réponse 204 No Content res.status(204).send(); }); // Démarrage du serveur app.listen(3000, () => { console.log('API REST démarrée sur le port 3000'); });

Documentation avec OpenAPI/Swagger

La documentation est cruciale pour les API REST. OpenAPI (anciennement Swagger) est devenu la norme de facto pour documenter les API REST de manière standardisée et interactive.

Spécification OpenAPI
# Exemple de spécification OpenAPI (Swagger) pour une API REST openapi: 3.0.3 info: title: API de gestion de produits description: API RESTful pour gérer un catalogue de produits version: 1.0.0 contact: name: API Support email: support@example.com url: https://www.example.com/support servers: - url: https://api.example.com/v1 description: Serveur de production - url: https://staging-api.example.com/v1 description: Serveur de staging paths: /products: get: summary: Liste tous les produits description: Retourne une liste paginée de produits avec support de filtrage parameters: - name: category in: query description: Filtre par catégorie schema: type: string - name: min_price in: query description: Prix minimum schema: type: number - name: page in: query description: Numéro de page pour la pagination 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 produits content: application/json: schema: type: object properties: data: type: array items: $ref: '#/components/schemas/Product' meta: $ref: '#/components/schemas/PaginationMeta' post: summary: Crée un nouveau produit requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ProductInput' responses: '201': description: Produit créé avec succès headers: Location: schema: type: string description: URL du nouveau produit content: application/json: schema: $ref: '#/components/schemas/Product' '400': description: Données invalides /products/{id}: get: summary: Récupère un produit spécifique parameters: - name: id in: path required: true schema: type: integer responses: '200': description: Détails du produit content: application/json: schema: $ref: '#/components/schemas/Product' '404': description: Produit non trouvé components: schemas: Product: type: object properties: id: type: integer name: type: string price: type: number category: type: string _links: type: object properties: self: type: object properties: href: type: string collection: type: object properties: href: type: string ProductInput: type: object required: - name - price properties: name: type: string minLength: 3 price: type: number minimum: 0 category: type: string PaginationMeta: type: object properties: total: type: integer page: type: integer limit: type: integer total_pages: type: integer

Bonnes pratiques

  • Noms au pluriel pour les collections - Utilisez /products plutôt que /product
  • Utilisation de noms et non de verbes - /products plutôt que /getProducts
  • Versioning de l'API - /v1/products pour permettre des évolutions futures
  • Pagination - Pour les collections qui peuvent contenir un grand nombre d'éléments
  • Filtrage, tri et recherche - Via des paramètres de requête
  • HATEOAS (Hypertext As The Engine Of Application State) - Inclusion de liens dans les réponses pour faciliter la navigation
  • Gestion des erreurs cohérente - Format standard pour les messages d'erreur
Applications concrètes

Cas d'usage

Applications mobiles

Les API REST sont idéales pour fournir des données aux applications mobiles, offrant une communication efficace entre le client mobile et le serveur.

Architectures microservices

Les API REST permettent la communication entre les différents microservices d'une architecture distribuée, assurant l'indépendance et la modularité.

Intégrations tierces

Les API REST facilitent l'intégration avec des services tiers et des partenaires, permettant l'échange de données de manière standardisée.

Applications web modernes (SPA)

Les Single Page Applications (React, Vue, Angular) utilisent des API REST pour récupérer et modifier les données sans recharger la page.

APIs REST publiques populaires

De nombreuses entreprises exposent leurs données et fonctionnalités via des API REST:

Twitter API
Stripe API
GitHub API
Google Maps API
Spotify API
OpenWeatherMap
SendGrid API
AWS REST APIs