MorphCluster Fastify

Данный пакет предоставляет готовые сервисы для обработки HTTP-запросов, организации единой точки входа (API Gateway), реверс-проксирования и раздачи статических файлов. Все компоненты наследуются от ServiceRequire и могут быть интегрированы в ServiceHost как обычные сервисы MorphCluster.

Fastify

Fastify — базовый класс для создания HTTP‑сервисов на основе Fastify. Интегрируется с MorphCluster, автоматически регистрирует маршруты, обрабатывает ошибки и поддерживает загрузку файлов, CORS и Swagger‑документацию.

Подключение

import { ServiceHost } from '@morphcluster/core';
import { Fastify } from '@morphcluster/web';

const host = new ServiceHost('main');
const web = new Fastify(host, {
  host: '0.0.0.0',
  port: 8080,
  title: 'My API',
  prefixUrl: '/api',
  maxFileSize: 2 * 1024 * 1024,
  disableProxy: false
});
host.addService(web);

Конфигурация

Параметр Тип По умолчанию Описание
host string 127.0.0.1 IP‑адрес для прослушивания
port number 0 (случайный) Порт (если 0, назначается ОС)
title string Fastify Service Заголовок для Swagger
prefixUrl string '' Общий префикс всех маршрутов
maxFileSize number 1000000 (1 МБ) Максимальный размер тела запроса и загружаемых файлов
disableProxy boolean false Отключить автоматическую регистрацию в HttpProxy
useProxy boolean true Устаревший синоним disableProxy (инвертирован)

Основные методы

addRoute(route)

Добавляет маршрут Fastify. Принимает объект со свойствами method, url и handler. Если маршрут с таким методом и URL уже существует, он заменяется.

web.addRoute({
  method: 'GET',
  url: '/hello',
  handler: (req, reply) => reply.send({ hello: 'world' })
});

restart()

Пересоздаёт экземпляр Fastify и заново регистрирует все накопленные маршруты. Полезно после массового добавления маршрутов.

Внутренние особенности


FastifyGateway

FastifyGateway — наследник Fastify, реализующий API Gateway. Он автоматически создаёт HTTP‑маршруты для всех запросов, зарегистрированных в GlobalServices. При появлении нового сервиса или изменении его схемы шлюз динамически перестраивает маршруты.

Подключение

import { FastifyGateway } from '@morphcluster/web';

const gateway = new FastifyGateway(host, {
  baseUrl: '/api',          // префикс всех маршрутов
  prefixUrl: '/gateway'     // собственный префикс Fastify (Swagger будет на /gateway/documentation)
});

Обычно GlobalServices передаётся через host или внедряется как опциональная зависимость GlobalServices. Также требуется Sessions, если не все запросы анонимны.

Как это работает

  1. При старте Gateway подписывается на событие onServiceChanged реестра GlobalServices.

  2. Для каждого сервиса и каждого его запроса, у которого задано свойство http (метод HTTP, например 'GET', 'POST'), создаётся маршрут вида:

    <baseUrl>/<serviceName>/<requestName>
    

    Имена сервисов и запросов конвертируются из CamelCase в kebab-case (MyServicemy-service, doSomethingdo-something).

  3. При получении HTTP‑запроса шлюз:

    • извлекает токен сессии из заголовка Authorization: Bearer <token>;
    • если запрос не помечен как anonymous, проверяет сессию через сервис Sessions;
    • если требуется needAdmin, проверяет флаг isAdmin в сессии;
    • подготавливает параметры запроса (request.body + IP + данные сессии);
    • логирует вызов с указанием сервиса и метода (если не noLogs);
    • вызывает service.sendRequest() соответствующего GlobalService;
    • результат возвращает клиенту как JSON, либо статус 204, если ответа нет;
    • в случае ошибки оборачивает её в ComplexError и возвращает клиенту (если пользователь — админ, ошибка всегда показывается).

Тонкая настройка запросов

В схеме сервиса для каждого запроса можно указать:

Генерация Swagger

Для каждого созданного маршрута автоматически формируется схема:


ServiceHealth

ServiceHealth — простой HTTP‑сервис, предоставляющий информацию о состоянии всех сервисов в ServiceHost. Расширяет Fastify и добавляет один маршрут GET /services.

Подключение

import { ServiceHealth } from '@morphcluster/web';

const health = new ServiceHealth(host, { prefixUrl: '/health' });

Ответ /services

{
  "allStarted": false,
  "notStarted": ["SomeService"],
  "noRequirements": ["DependencyService"],
  "fullServices": [
    {
      "name": "MyService",
      "starting": false,
      "started": true,
      "requirements": []
    }
  ]
}

HttpProxy

HttpProxy — обратный прокси‑сервер, позволяющий объединить несколько внутренних HTTP‑серверов (и WebSocket) под одним портом. Сам является сервисом MorphCluster и может динамически добавлять/удалять маршруты.

Подключение

import { HttpProxy } from '@morphcluster/web';

const proxy = new HttpProxy(host, { port: 80, host: '0.0.0.0', proxyTimeout: 60000 });

Конфигурация

Параметр Тип По умолчанию Описание
port number обязательно Порт, на котором будет слушать прокси
host string '0.0.0.0' IP для прослушивания
proxyTimeout number 120000 Таймаут проксирования запросов (мс)

Методы (доступны как запросы сервиса)

addProxy({ url, address, type? })

Добавляет новый прокси‑маршрут.

delProxy({ url })

Удаляет маршрут по URL-префиксу.

list()

Возвращает массив всех текущих маршрутов.

Механизм работы

Автоматическая регистрация сервисов Fastify

Любой сервис, наследующий Fastify, при старте (если disableProxy !== true) автоматически регистрирует себя в HttpProxy, добавляя маршрут со своим prefixUrl и адресом http://127.0.0.1:<порт>. Это позволяет собирать все HTTP‑интерфейсы под единым входным портом.


HttpStatic

HttpStatic — сервис для раздачи статических файлов (HTML, CSS, JS, изображений и т.д.). Поддерживает кэширование по ETag и автоматическую регистрацию в HttpProxy (опционально).

Подключение

import { HttpStatic } from '@morphcluster/web';

const staticServer = new HttpStatic(host, {
  prefixUrl: '/static',
  staticPath: './public',
  port: 8081,
  useProxy: true
});

Конфигурация

Параметр Тип По умолчанию Описание
prefixUrl string '' URL‑префикс, по которому доступна статика
staticPath string './static' Локальная директория с файлами (разрешается относительно Config.packageRoot)
host string 127.0.0.1 IP для прослушивания
port number 0 Порт
useProxy boolean false Автоматически добавить прокси‑маршрут в HttpProxy

Поведение


Swagger UI

Встроенный модуль Swagger UI реализован как Fastify‑плагин (fastifySwaggerUi). Он автоматически добавляется ко всем сервисам, наследующим Fastify, и предоставляет интерфейс по адресу <prefixUrl>/documentation.

Файлы

Особенности


Схемы сервисов

FastifyGateway (src/fastify-gateway/service-schema.mjs)

{
  "name": "FastifyGateway",
  "description": "HTTP шлюз для сервисов",
  "requests": [
    {
      "name": "recreateRoutes",
      "description": "Пересоздать маршруты",
      "anonymous": false,
      "needAdmin": true,
      "noLogs": true,
      "http": null,
      "request": {},
      "response": {}
    }
  ]
}

Запрос recreateRoutes позволяет администратору принудительно перестроить все маршруты шлюза.

HttpProxy (src/http-proxy/service-schema.js)

Содержит запросы:

Все административные запросы требуют сессии с правами администратора.


Экспорт

Пакет экспортирует все основные классы через src/index.js:

import {
  Fastify,
  FastifyGateway,
  ServiceHealth,
  HttpProxy,
  HttpStatic
} from '@morphcluster/web';

Вспомогательные функции и схема Swagger UI доступны для внутреннего использования, но не экспортируются наружу.


Интеграция с MorphCluster Core

Все описанные сервисы построены на базе ServiceRequire, поэтому могут использовать:

Для корректной работы в системе, использующей GlobalServices, необходимо, чтобы HttpProxy, Sessions (если нужна аутентификация) и все сервисы, к которым обращается FastifyGateway, были зарегистрированы в реестре.


Revision #2
Created 21 June 2026 15:35:19 by Георгий
Updated 26 June 2026 13:52:59 by Георгий