API Gateway для микросервисов на JavaScript: полный гайд

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Зачем вашему проекту API Gateway на JavaScript?

Представьте, что ваш backend — это огромный торговый центр. Внутри него десятки магазинов (микросервисов): один продаёт книги, другой — одежду, третий — электронику. Каждый магазин имеет свой вход, свои правила и свой язык. А теперь представьте, что посетитель (клиентское приложение) должен обойти все эти входы, чтобы купить одну футболку. Хаос, правда?

В мире веб-разработки эту проблему решает API Gateway — единая точка входа для всех микросервисов. Он как администратор торгового центра: направляет запросы, проверяет билеты (токены), собирает данные из разных магазинов и отдаёт клиенту готовый ответ. И сегодня мы разберём, как написать такой шлюз на чистом JavaScript с использованием Node.js.

Эта статья будет полезна как новичкам, которые только знакомятся с архитектурой микросервисов, так и опытным разработчикам, которые хотят увидеть рабочие примеры кода. Поехали!

Что такое API Gateway и зачем он нужен?

API Gateway — это серверный компонент, который выступает промежуточным слоем между клиентом и внутренними сервисами. Он берёт на себя:

  • Маршрутизацию — направляет запросы к нужному микросервису.
  • Аутентификацию и авторизацию — проверяет, имеет ли пользователь доступ.
  • Агрегацию данных — собирает ответы от нескольких сервисов в один.
  • Лимитирование запросов — защищает backend от перегрузок.
  • Трансформацию протоколов — например, конвертирует REST в GraphQL.

Для JavaScript сервисов (особенно на Node.js) API Gateway — это естественный выбор. Он легко пишется на Express, Koa или Fastify, а главное — позволяет сохранить единый стиль кода во всём проекте.

Проектируем структуру API Gateway на Node.js

Прежде чем писать код, давайте определимся с архитектурой. Допустим, у нас есть три микросервиса:

  • users-service — управление пользователями (порт 3001).
  • orders-service — заказы (порт 3002).
  • products-service — каталог товаров (порт 3003).

Клиент (фронтенд) обращается только к Gateway на порту 8080. Gateway сам решает, куда направить запрос.

Шаг 1. Базовая настройка Express

Создадим новый проект и установим зависимости:

mkdir api-gateway
cd api-gateway
npm init -y
npm install express http-proxy-middleware dotenv

Теперь напишем простой Gateway, который проксирует запросы к сервисам:

// gateway.js
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
require('dotenv').config();

const app = express();
const PORT = process.env.PORT || 8080;

// Маршруты для микросервисов
app.use('/users', createProxyMiddleware({
  target: 'http://localhost:3001',
  changeOrigin: true,
}));

app.use('/orders', createProxyMiddleware({
  target: 'http://localhost:3002',
  changeOrigin: true,
}));

app.use('/products', createProxyMiddleware({
  target: 'http://localhost:3003',
  changeOrigin: true,
}));

app.listen(PORT, () => {
  console.log(`API Gateway запущен на порту ${PORT}`);
});

Вот и всё! Теперь любой запрос к /users автоматически перенаправляется на users-service. Но это только начало. Настоящий Gateway должен делать больше.

Добавляем аутентификацию и проверку токенов

Одна из главных задач API Gateway — централизованная аутентификация. Вместо того чтобы проверять JWT в каждом микросервисе, мы делаем это один раз в шлюзе.

Добавим middleware для проверки токена:

// middleware/auth.js
const jwt = require('jsonwebtoken');

const authMiddleware = (req, res, next) => {
  const authHeader = req.headers.authorization;
  if (!authHeader) {
    return res.status(401).json({ error: 'Токен не предоставлен' });
  }

  const token = authHeader.split(' ')[1]; // Bearer <token>

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded; // добавляем данные пользователя в запрос
    next();
  } catch (err) {
    return res.status(403).json({ error: 'Неверный токен' });
  }
};

module.exports = authMiddleware;

Теперь подключим его к определённым маршрутам:

// gateway.js (фрагмент)
const authMiddleware = require('./middleware/auth');

// Защищённые маршруты (требуют токен)
app.use('/orders', authMiddleware, createProxyMiddleware({
  target: 'http://localhost:3002',
  changeOrigin: true,
}));

// Публичные маршруты (без аутентификации)
app.use('/products', createProxyMiddleware({
  target: 'http://localhost:3003',
  changeOrigin: true,
}));

Таким образом, мы создали единую точку входа с контролем доступа. Если токен просрочен или неверен — пользователь получит ошибку, не доходя до микросервиса.

Агрегация данных: собираем ответы из разных сервисов

Часто клиенту нужны данные из нескольких микросервисов одновременно. Например, чтобы отобразить страницу товара, нужно взять описание из products-service и отзывы из reviews-service. Без Gateway фронтенд делал бы два запроса. С Gateway — один.

Напишем эндпоинт-агрегатор:

// routes/aggregate.js
const axios = require('axios');

const aggregateProduct = async (req, res) => {
  try {
    const productId = req.params.id;

    // Параллельные запросы к сервисам
    const [productResponse, reviewsResponse] = await Promise.all([
      axios.get(`http://localhost:3003/products/${productId}`),
      axios.get(`http://localhost:3004/reviews/${productId}`),
    ]);

    const productData = productResponse.data;
    const reviewsData = reviewsResponse.data;

    // Объединяем данные
    const result = {
      ...productData,
      reviews: reviewsData,
    };

    res.json(result);
  } catch (error) {
    res.status(500).json({ error: 'Ошибка агрегации данных' });
  }
};

module.exports = { aggregateProduct };

Подключаем в Gateway:

const { aggregateProduct } = require('./routes/aggregate');

app.get('/aggregate/products/:id', aggregateProduct);

Теперь клиент получает полную информацию о товаре за один запрос. Это снижает нагрузку на сеть и ускоряет работу приложения.

Лимитирование запросов (Rate Limiting)

Без защиты ваш Gateway может стать жертвой DDoS-атаки или случайного всплеска трафика. Добавим лимитирование с помощью пакета express-rate-limit:

npm install express-rate-limit
// middleware/rateLimit.js
const rateLimit = require('express-rate-limit');

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 минут
  max: 100, //                

Блоги

Рекомендаций по книгам