Привет, Хабр! Представляю вашему вниманию перевод статьи "Creating a simple API Gateway in ASP.NET Core". Время чтения: ~10 минут В моей предыдущей статье, JWT аутентификация для микросервисов в .NET, я рассмотрел процесс создания микросервиса для аутентификации пользователей. Это может быть использовано для проверки личности пользователя перед совершением любых действий в других компонентах системы.   Другой жизненно необходимый компонент для работы продукта это API-шлюз — система между приложением и бэкэндом, которая, во-первых, маршрутизирует входящие запросы на соответствующий микросервис, и во-вторых, авторизует пользователя. Существует много фреймворков которые могут быть использованы для создания API-шлюза, например, Ocelot в .NET core или Netflix Zuul в Java. Тем не менее, в этой статье я опишу процесс создания простого API-шлюза с нуля в .NET Core. Для начала создадим новое приложение, выбрав ASP.NET Core Web Application в окне создания проекта и Empty в качестве шаблона.   В проекте будут лежать классы Startup и Program. Для нас самой важной частью является метод Configure класса Startup. Здесь мы можем обработать входящий HTTP-запрос и ответить на него. Возможно, в методе Configure будет находится следующий код: Так как именно в методе Configure мы будем обрабатывать запросы, напишем необходимую логику: Сначала мы создаем объект типа Router. В его задачи входит хранение существующих маршрутов, валидация и отправка запросов согласно маршрутам. Чтобы сделать код более чистым, будем подгружать маршруты из JSON-файла. В итоге получается следующая логика: после того, как запрос поступит на шлюз, он будет перенаправлен маршрутизатору, который, в свою очередь, отправит его на соответствующий микросервис. Перед тем как писать класс Router, создадим файл routes.json. В этом файле укажем список маршрутов, каждый из которых будет содержать внешний адрес (endpoint) и адрес назначения (destination). Также, мы добавим флаг, сигнализирующий о необходимости авторизации пользователя перед перенаправлением. Вот как примерно может выглядеть такой файл: Мы теперь знаем, что каждый Route должен иметь endpoint и destination, а каждый Destination должен иметь поля uri и requiresAuthentication. Теперь напишем класс Destination, помня о том. Я добавлю два поля, два конструктора и приватный конструктор без параметров для JSON-десериализации. Также, будет правильно написать в этом классе метод SendRequest. Этим мы покажем, что каждый объект класса Destination будет ответственнен за отправку запроса. Этот метод будет принимать объект типа HttpRequest, который описывает входящий запрос, вынимать оттуда всю необходимую информацию и отправлять запрос на целевой URI. Для этого напишем вспомогательный метод CreateDestinationUri, который будет соединять строки с адресом и параметры адресной строки (query string) от клиента. Теперь мы можем написать метод SendRequest, который будет отправлять запрос на микросервис и получать ответ обратно. Перед написанием класса Router, нам нужно создать логику для десериализации JSON-файла с маршрутами. Я создам для этого вспомогательный класс, в котором будет два метода: один для создания объекта из JSON-файла, а другой для десериализации. Последнее, что мы сделаем перед написанием Router — опишем модель маршрута: Теперь напишем класс Router, добавив туда поля и констурктор. Я использую динамический тип (dynamic type) для чтения из JSON и записи в него свойств объекта. Теперь все готово для описания главной фнукциональности API-шлюза: маршрутизация и авторизация пользователя, которая будет происходить в методе RouteRequest. Нам нужно распаковать базовую часть внешнего адреса (base endpoint) из объекта запроса. Например, для адреса /movies/add базой будет /movies/. После этого, нам нужно проверить, есть ли описание данного маршрута. Если да, то авторизуем пользователя и отправляем запрос, иначе возвращаем ошибку. Я также создал класс ConstructErrorMessage для удобства. Для авторизации, я предпочел следующий путь: извлекаем токен из заголовка запроса и отправляем как параметр запроса. Возможен и другой вариант: оставить токен в заголовке, тогда извлекать его должен уже микросервис, которому предназначается запрос. Создание базового API-шлюза не требует много усилий, но он не предоставит должной фукнциональности. Если вам нужен балансировщик нагрузки, вы можете посмотреть на уже существующие фреймворки или платформы, которые предлагают библиотеки для маршрутизации запросов. Весь код из этой статьи доступен в репозитории на GitHub Программист, разработчик, переводчик