Introduction : pourquoi votre projet a-t-il besoin d'un API Gateway ?
\n\nImaginez : vous développez une startup ou une application d'entreprise en TypeScript. Vous avez déjà un service utilisateurs, un service commandes et un service notifications. Chacun vit sur son propre port (ou même sur son propre serveur), communique en HTTP, utilise sa propre base de données. Tout fonctionne, mais le client (frontend, application mobile) commence à suffoquer : pour afficher une page de profil, il doit effectuer 4 à 5 requêtes vers différents services, gérer différents formats d'erreurs, et en plus s'authentifier sur chacun.
\n\nC'est là qu'intervient l'API Gateway — un point d'entrée unique pour tous les clients. Il prend en charge le routage, l'authentification, l'agrégation de données, la mise en cache et même la transformation des réponses. Dans cet article, nous allons écrire un véritable API Gateway en TypeScript from scratch, analyser les patterns et anti-patterns, et montrer comment éviter les pièges.
\n\nQu'est-ce qu'un API Gateway en termes simples
\n\nUn API Gateway est une couche intermédiaire entre le client et vos services internes. Le client (navigateur, application mobile, API externe) ne frappe qu'à la porte du Gateway. Le Gateway examine le chemin de la requête, vérifie le token, et redirige la requête vers le microservice approprié. Parfois, il assemble même la réponse à partir de plusieurs services en une seule — c'est ce qu'on appelle l'agrégation.
\n\nPourquoi est-ce nécessaire dans l'écosystème TypeScript ? Parce que TypeScript nous offre des types, des interfaces et de la rigueur, et le Gateway est l'endroit idéal pour la validation et la mise en conformité des données avec un contrat unique.
\n\nArchitecture : comment ça fonctionne en TypeScript
\n\nConcevons une architecture simple mais fonctionnelle. Nous aurons :
\n\n- \n
- Gateway (notre service TypeScript) — port 3000, point d'entrée unique. \n
- Service utilisateurs (User Service) — port 4001, API REST. \n
- Service commandes (Order Service) — port 4002, API REST. \n
- Service notifications (Notification Service) — port 4003, API REST. \n
Tous les services internes vivent dans leur propre réseau (par exemple, Docker network) et ne sont pas visibles de l'extérieur. Le client ne communique qu'avec le Gateway.
\n\n// Structure du projet\ngateway/\n├── src/\n│ ├── routes/\n│ │ ├── userRoutes.ts\n│ │ ├── orderRoutes.ts\n│ │ └── notificationRoutes.ts\n│ ├── middleware/\n│ │ ├── authMiddleware.ts\n│ │ ├── rateLimiter.ts\n│ │ └── cacheMiddleware.ts\n│ ├── services/\n│ │ └── proxyService.ts\n│ ├── types/\n│ │ └── index.ts\n│ └── index.ts\n├── package.json\n└── tsconfig.json\n\n\nÉcrire un API Gateway de base en TypeScript
\n\nCommençons par installer les dépendances. Nous aurons besoin d'Express (le framework le plus populaire), de http-proxy-middleware pour le proxy, et de quelques utilitaires.
\n\nnpm init -y\nnpm install express http-proxy-middleware cors helmet express-rate-limit\nnpm install -D typescript @types/node @types/express ts-node nodemon\n\n\nCréons le fichier tsconfig.json :
{\n "compilerOptions": {\n "target": "ES2020",\n "module": "commonjs",\n "outDir": "./dist",\n "rootDir": "./src",\n "strict": true,\n "esModuleInterop": true,\n "skipLibCheck": true,\n "forceConsistentCasingInFileNames": true\n },\n "include": ["src/**/*"],\n "exclude": ["node_modules"]\n}\n\n\nÉcrivons maintenant le fichier principal src/index.ts :
import express, { Request, Response } from 'express';\nimport cors from 'cors';\nimport helmet from 'helmet';\nimport { createProxyMiddleware } from 'http-proxy-middleware';\nimport { authMiddleware } from './middleware/authMiddleware';\nimport { rateLimiter } from './middleware/rateLimiter';\n\nconst app = express();\nconst PORT = process.env.PORT || 3000;\n\n// Middleware globaux\napp.use(helmet());\napp.use(cors());\napp.use(express.json());\napp.use(rateLimiter);\n\n// Proxy pour le service utilisateurs\napp.use('/api/users', auth