Создание клиентов OpenAPI API для Angular
Спецификация OpenAPI упрощает процесс разработки RESTful API, предлагая стандартный документ, который разработчики могут использовать для автоматической генерации документации по API, валидаторов и клиентских SDK. Разработчики Angular могут ускорить выполнение первоначальных задач по разработке интерфейса, создав клиентские модули API с использованием спецификаций OpenAPI, не тратя время на написание клиентов API с нуля.
В этом руководстве мы узнаем, как создавать клиенты OpenAPI API для веб-проектов Angular.
Преимущества использования автоматически генерируемых API-клиентов
Использование автоматически генерируемых клиентов API дает вашим проектам Angular следующие преимущества.
Быстрое развитие
Инструменты генерации кода OpenAPI позволяют разработчикам создавать клиенты RESTful API путем импорта файла спецификации OpenAPI YAML/JSON без написания исходных текстов реализации HTTP-клиента. Например, вы можете легко вызвать метод GetProducts() сгенерированного клиента, не реализуя его с помощью HttpClient, Axios или Fetch, чтобы отправить HTTP-запрос на получение /products.
Уменьшение количества ошибок разработчика
Автоматическая генерация кода устраняет распространенные ошибки разработчиков, такие как проблемы с наименованием методов, отсутствующие поля в ответах и проблемы с реализацией HTTP-клиента в вручную написанных клиентах API.
Поддержание согласованности
Генераторы клиентов OpenAPI полагаются на файлы спецификаций API и базовые параметры генерации кода (например, стили оформления букв), поэтому они всегда будут генерировать согласованные реализации методов, которые разработчики приложений смогут использовать без путаницы.
Простое портирование кодовой базы
Как и в случае с кодом на Angular TypeScript, разработчики могут создавать API-клиенты для нескольких языковых целевых объектов, поддерживая один и тот же интерфейс API. Предположим, вам нужно перенести ваше приложение Angular на другой язык и платформу. В этом случае вам не нужно беспокоиться об автоматически генерируемом исходном коде клиента Angular API, поскольку генераторы кода OpenAPI поддерживают несколько целевых языков / платформ, например Java, Rust, Android и т.д..
Создание клиентов OpenAPI в Angular
Давайте узнаем, как создать API-клиент для проекта Angular с помощью программы OpenAPI Generator с открытым исходным кодом. Проект OpenAPI Generator предлагает интерфейс командной строки для создания клиентских модулей API для нескольких целевых языков путем импорта файла спецификации API в формате YAML/JSON.
Мы создадим API-клиент для примера проекта Angular и будем использовать его для подключения к простому серверу RESTful через интерфейс приложения Angular.
Создайте новый проект Angular, чтобы продолжить работу с этим руководством:
ng new openapi-demo cd openapi-demo
Поиск файла спецификации OpenAPI
Во-первых, вам следует найти файл спецификации OpenAPI вашего RESTful API-сервера, чтобы сгенерировать API-клиент для вашего интерфейса Angular. В этом руководстве мы будем использовать простой, предварительно разработанный сервер RESTful API и его файл спецификации OpenAPI для создания нового клиента API. Мы протестируем созданный клиент, используя пример реализации интерфейса приложения Angular.
Получите образец исходного кода сервера RESTful API, который реализует несколько конечных точек для добавления, извлечения и удаления простых объектов продукта, клонировав этот репозиторий GitHub. Создайте новый каталог с именем server в проекте Angular и клонируйте репозиторий GitHub внутри него следующим образом:
mkdir server cd server git clone https://github.com/codezri/openapi-generator-node.git .
Установите зависимости и запустите сервер RESTful:
npm install npm start # --- or --- # yarn yarn start
Сценарий запуска генерирует файл спецификации API openapi.yaml на основе аннотаций JSDoc с использованием библиотеки [swagger-jsdoc](https://github.com/Surnet/swagger-jsdoc) и запускает сервер RESTful на порту 8080. Теперь мы можем использовать сгенерированный файл спецификации OpenAPI для создания API-клиента для Angular:
Â'Â
В производственных системах вам, возможно, придется запросить спецификации API у команды серверных разработчиков, если вы являетесь интерфейсным разработчиком, или экспортировать их самостоятельно (например, из консоли API designer, такой как AWS API Gateway), если вы являетесь полнофункциональным разработчиком.разработчик стека.
Установка зависимостей
Перед установкой пакетов зависимостей для генерации кода убедитесь, что на вашем компьютере установлена рабочая среда Java Runtime Environment (JRE) версии 11 или выше, поскольку CLI генератора OpenAPI использует артефакты .jar для генерации кода. Вы можете подтвердить установку JRE, введя команду java в терминале.
Установите OpenAPI Generator CLI в качестве зависимости разработчика в свой проект Angular:
npm install @openapitools/openapi-generator-cli -D # --- or --- # yarn add @openapitools/openapi-generator-cli -D
После установки мы можем использовать команду openapi-generator-cli в скриптах package.json для генерации клиентских исходных текстов API для приложения Angular в указанном выходном каталоге.
Создание исходного кода клиента API
Обновите раздел сценариев NPM для автоматической генерации клиента перед запуском и сборкой приложения:
... "scripts": { "ng": "ng", "generate": "openapi-generator-cli generate -i server/openapi.yaml -g typescript-angular -o src/app/modules/openapi --additional-properties fileNaming=kebab-case,withInterfaces=true --generate-alias-as-model", "start": "npm run generate && ng serve", "build": "npm run generate && ng build", ...
Приведенный выше скрипт generate NPM генерирует исходный код клиента API с помощью команды openapi-generator-cli с использованием модуля typescript-angular code generator. Скрипт generate выполняет команду openapi-generator-cli с несколькими параметрами CLI, такими как --additonal-properties, для генерации клиентского кода, соответствующего стилю кодирования Angular и рекомендуемым соглашениям об именовании файлов. Мы обсудим настройку генератора кода в следующем разделе этого руководства.
Запустите скрипт generate для автоматической генерации клиентского исходного кода в src/app/modules/openapi, как показано ниже:
Â'Â
Просмотрите автоматически созданную клиентскую реализацию и посмотрите, как она создает новый сервис, определяет модели и экспортирует необходимые элементы:
Â'Â
Вот несколько важных фактов, на которые следует обратить внимание в этом процессе генерации кода:
-
Программа-генератор кода добавляет URL-адрес сервера RESTful API, используя раздел servers в спецификации API
Автоматически сгенерированные исходные операции клиента создаются на основе поля OperationId, т.е. идентификатор операции GetProducts помогает генератору кода определить метод GetProducts(), который вызывает конечную точку GET /products
Генератор кода создает сервисы Angular на основе тегов для каждой конечной точки. В примере спецификации API мы использовали только тег product, поэтому созданный клиент содержит только сервисный файл product.service.ts
Интеграция сгенерированного клиентского источника
Автоматически созданный сервис Angular готов к использованию с нашим образцом приложения Angular.
Автоматически сгенерированный клиентский источник использует класс Angular HttpClient для выполнения HTTP-запросов, поэтому включите его в приложении, обновив файл app.config.ts следующим образом:
// ... import { provideHttpClient } from '@angular/common/http'; export const appConfig: ApplicationConfig = { providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideHttpClient()] };
Затем импортируйте автоматически сгенерированный ProductService и элементы продукта в файл app.component.ts:
import { ProductService, Product } from './modules/openapi';
Внедрите экземпляр класса ProductService, обновив конструктор компонента:
constructor(private productService: ProductService) {}
Ознакомьтесь с доступными методами внедренной службы, используя функцию автозавершения в редакторе кода. Вы увидите все операции, которые вы определили в файле спецификации API, как показано в следующем предварительном просмотре:
Â'Â
Используя этот подход, вы можете использовать любую автоматически сгенерированную клиентскую службу в любом компоненте Angular.
Вызов REST API с помощью клиентских методов
Чтобы сделать это руководство более практичным и интерактивным, мы создадим простой пользовательский интерфейс для добавления, перечисления и удаления элементов продукта с помощью созданного клиента OpenAPI.
Сначала обновите файл app.component.ts, добавив в него следующие необходимые импортные данные, чтобы начать разработку приложения:
// ... import { Observable } from 'rxjs'; import { AsyncPipe } from '@angular/common'; import { FormsModule } from '@angular/forms'; // ...
Обновите раздел импорта в декораторе компонентов с помощью AsyncPipe и FormsModule следующим образом:
@Component({ // ... imports: [RouterOutlet, AsyncPipe, FormsModule], })
Обновите класс компонента приложения, реализовав методы добавления, перечисления и удаления продуктов:
export class AppComponent { products$!: Observable<Product[]>; productName!: string; constructor(private productService: ProductService) {} ngOnInit() { this.loadProducts(); } loadProducts() { this.products$ = this.productService.getProducts(); } deleteProduct(productId: number) { this.productService.deleteProduct(productId) .subscribe(() => this.loadProducts()); } createProduct() { this.productService.createProduct({name: this.productName}) .subscribe(() => { this.productName = ''; this.loadProducts(); }) } }
В приведенной выше реализации компонента используются методы createProduct(), GetProducts() и deleteProduct() из автоматически сгенерированной клиентской службы API для вызова конечных точек RESTful API.
Обновите файл app.component.html следующим образом, чтобы создать простой пользовательский интерфейс для вызова вышеуказанных методов компонента и отображения продуктов:
<h1>Products</h1> <div> <input type="text" [(ngModel)]="productName" placeholder="Product name"> <button (click)="createProduct()">Create</button> </div> <div> <ul> @for (product of (products$ | async); track product.id) { <li>{{ product.name }} <span (click)="deleteProduct(product.id!)">âÂÂï¸Â</span></li> } </ul> </div> <router-outlet />
Наконец, оформите вышеуказанную HTML-структуру, используя следующие стили в файле app.component.css:
ul { margin: 1em 0 0 0; padding: 0; } li { list-style: none; background-color: #eee; padding: 0.5em; margin-bottom: 0.2em; } li span { cursor: pointer; font-size: 0.75em; padding-left: 0.5em; } button, input { font-size: 0.8em; padding: 0.3em 1em 0.3em 1em; margin-right: 0.8em; }
Запустите пример сервера RESTful на порту 8080 и запустите свое приложение Angular. Теперь ваше приложение Angular взаимодействует с сервером через автоматически созданный клиент OpenAPI и позволяет вам отображать, добавлять и удалять объекты продукта, как показано ниже.:
Â'Â
Как показано в приведенной выше демонстрации, автоматически сгенерированный клиент OpenAPI отправляет HTTP-запросы на сервер при вызове его методов.
В этом руководстве мы позволяем генератору кода определять URL-адрес сервера API с помощью раздела OpenAPI servers, но вы можете задать его из app.config.ts, не используя раздел servers в спецификации API:
import { BASE_PATH } from './modules/openapi'; export const appConfig: ApplicationConfig = { providers: [..., { provide: BASE_PATH, useValue: 'http://localhost:8080' }] };
Приведенный выше фрагмент кода использует введенный токен BASE_VALUE для установки URL-адреса сервера API с помощью пользовательского объекта provider.
Кроме того, вы также можете напрямую изменить свойство basePath конфигурации службы:
this.productService.configuration.basePath = "http://localhost:8080";
Вызов защищенных конечных точек
В приведенном выше примере реализации RESTful server использовался общедоступный API без защищенных конечных точек, чтобы упростить демонстрацию генерации клиентского кода OpenAPI. Однако большинство современных RESTful серверов реализуют защищенные конечные точки, используя стратегию аутентификации с использованием токена-носителя. Генератор OpenAPI поддерживает стратегию аутентификации на предъявителя и генерирует код для включения HTTP-заголовка Authorization для вызова защищенных конечных точек.
Давайте проверим, как генерировать код для защищенных конечных точек, использующих аутентификацию на предъявителя. Предположим, что примерный сервер RESTful обрабатывает конечную точку /products как защищенную конечную точку, проверяя токен предъявителя JWT.
Определите стратегию безопасности JWT в разделе компонентов OpenAPI, обновив файл server/openapi.yaml:
... components: securitySchemes: JWT: type: http scheme: bearer bearerFormat: JWT ...
Теперь используйте стратегию безопасности JWT для конечной точки GET /products следующим образом:
... paths: /products: get: security: - JWT: [] operationId: getProducts ...
Теперь сгенерированный клиент будет содержать код аутентификации с использованием токена-носителя, который установит заголовок авторизации для вызова конечной точки GET /products. Токен JWT обычно получается после успешного входа пользователя в систему, но мы можем использовать случайный токен для тестирования реализации аутентификации на предъявителя в автоматически сгенерированном клиенте API. Установите тестовый токен JWT с помощью метода ngInit() следующим образом:
ngOnInit() { this.productService.configuration.credentials = { JWT: 'access_token' }; this.loadProducts(); }
Повторно запустите проект Angular для создания клиента и запуска примера приложения. Вы заметите значение тестового токена JWT только в заголовках защищенного вызова конечной точки GET /products, как показано на следующей записи экрана:
Â'Â
Поток запросов на обновление токена еще не реализован в генераторе кода Angular проекта OpenAPI Generator, но вы можете реализовать поток обновлений токена с помощью HTTP-перехватчиков, как показано в следующем примере фрагмента кода:
export const appConfig: ApplicationConfig = { providers: [..., provideHttpClient(withInterceptors([refreshTokenInterceptor]))] };
В приведенном выше фрагменте кода refreshTokenInterceptor - это перехватчик Angular HTTP, который вызывает ваш сервер RESTful для запроса нового токена, используя сохраненный токен обновления, если срок действия текущего токена-носителя JWT истек.
Узнайте больше о потоках аутентификации REST API из этой статьи.
Настройка генератора OpenAPI
CLI-программа OpenAPI Generator поддерживает несколько глобальных и зависящих от целевого языка свойств конфигурации генерации кода с помощью параметров CLI. Например, ранее мы использовали конфигурационное свойство fileNaming=kebab-case после опции CLI--additional-properties, чтобы использовать kebab case для именования исходного файла Angular.
Вот некоторые общие свойства конфигурации, которые вам могут понадобиться для использования в вашем клиентском проекте OpenAPI:
Просмотрите все поддерживаемые свойства конфигурации, специфичные для Angular, введя следующую команду в вашем терминале:
npx @openapitools/openapi-generator-cli config-help -g typescript-angular
Подкомандаgenerate командной строки генератора кода также поддерживает различные параметры командной строки для настройки процесса генерации общего кода. Вы можете просмотреть все поддерживаемые параметры командной строки generate, введя следующую команду на своем терминале:
npx @openapitools/openapi-generator-cli help generate
Рекомендации по использованию автоматически создаваемых клиентов OpenAPI
Автоматически генерируемые коды пишутся не только людьми, уделяющими особое внимание удобочитаемости и сопровождаемости кода - генераторы кода обычно создают код, ориентированный на функциональность, используя шаблоны, основанные на входных параметрах. Таким образом, автоматически сгенерированный код не должен использоваться в кодовой базе приложения Angular, которую вы написали вручную. Придерживайтесь следующих рекомендаций при использовании автоматически сгенерированных клиентов OpenAPI, чтобы улучшить качество всей кодовой базы:
-
Поместите автоматически сгенерированный исходный код клиента в отдельный каталог, куда вы не добавляете исходные файлы вручную. например, src/api/modules/apiclient
Избегайте добавления автоматически сгенерированных файлов в свой репозиторий Git, чтобы сохранить дерево исходных текстов Git чистым и легким. Вы можете в любое время попросить членов своей команды разработчиков использовать сценарии NPM для создания новых клиентских исходных текстов
Опубликуйте исходный код клиента в удаленном репозитории NPM, если вам необходимо изолировать его от кодовой базы вашего приложения Angular
Если ваша компания инвестирует в современные принципы DevOps, команда серверных разработчиков может использовать сценарии автоматизации для автоматической публикации новых клиентских версий Angular API при публикации новой версии RESTful API
Настройте программу-генератор кода в соответствии со стилем программирования вашей команды для обеспечения плавной интеграции с кодом, написанным вручную
Напишите модульные или интеграционные тесты для проверки автоматически сгенерированной клиентской реализации и запустите их автоматически перед публикацией новой версии клиента.
Никогда не обновляйте автоматически сгенерированный код вручную для исправления ошибок или реализации функций. Вместо этого сообщите об ошибках в службу поддержки генератора OpenAPI или реализуйте недостающие функции самостоятельно, используя перехватчики Angular HTTP
Вывод
В этом руководстве мы рассмотрели преимущества использования генераторов OpenAPI-клиентов и создали пример клиента для приложения Angular, импортировав файл спецификации YAML API. Мы также обсудили рекомендации, которым следует следовать при использовании автоматически созданных OpenAPI-клиентов в проектах Angular.
Интерфейс OpenAPI Generator CLI позволяет создавать исходные тексты клиентских API для множества целевых языков и фреймворков, включая Angular framework. Программа code generator автоматически создает модели и сервисы, которые мы можем напрямую использовать в проектах Angular без написания единой строки кода для ручной реализации клиентских API, включая аутентификацию на предъявителя.
Автоматически сгенерированный код написан не только человеком, поэтому нам придется следовать вышеупомянутым рекомендациям, чтобы гарантировать качество и ремонтопригодность исходной кодовой базы приложения Angular.