документация api спецификации что это
API документация: как документировать API для веб-сервисов?
Документирование API при разработке
Многие из нас при выполнении своих обязанностей на работе сталкиваются с необходимостью заглянуть в какой-либо справочник, который даст нам ответ на вопрос. Если вы пользователь ERP / CRM-системы, то при возникших вопросах сразу обращаетесь в ИТ-поддержку. Если вы юрист, то нуждаетесь в соответствующем кодексе, по которому у вас возник вопрос. А если вы занимаетесь разработкой веб-приложений для своего бизнеса или для своих клиентов, то вам будут просто необходимы стандарты разработки и документация для вашего API. В каждой сфере есть своя документация, из которой черпают люди информацию, необходимую им для выполнения своей работы.
Казалось бы, всё так просто. Но в сфере IT (Information technology) всё меняется очень интенсивно. Взаимосвязи программ, приложений и т.п. через API (Application Programming Interface) тоже постоянно меняются. Многие программисты сталкиваются с необходимостью посмотреть стандарты своего языка программирования, API для текущей задачи, способы все это зафиксировать, чтоб было проще и комфортнее работать через документацию в дальнейшем.
Проблема документирования API
API-документация — это техническая документация, в которой фиксируются инструкции о том, как эффективно использовать программное API, аппаратное SCPI или web API.
Для активно развивающихся продуктов поддержка документации API играет немаловажную роль, но при этом стоит не забывать об актуальности этих данных.
Проблема стандартизации API
Допустим, документирование API было доведено до актуальности, и теперь у нас в доступе всегда безошибочная информация. Но, к сожалению, при наличии актуальной документации трудности не заканчиваются. Получившееся API может быть настолько сложным и неудобным, что работа с ним может стать кошмаром. Ведь в первую очередь работать с ним будут люди, а уже только потом программа. Очевидно, что нужен некий стандарт разработки API, чтобы разработчики даже при беглом ознакомлении понимали, как с ним корректно взаимодействовать. Также наличие стандарта API позволяет использовать средства автоматической кодогенерации, что существенно повышает скорость разработки.
Как решается задача документации API
Прежде чем перейти к решению возникших проблем, необходимо знать существующие протоколы реализации веб-сервисов, как они работают, их особенности. А также познакомиться с различными инструментами для стандартизации API-интерфейсов.
Краткий обзор существующих веб-сервисов API
В веб-разработке активно используются веб-интерфейсы или web API. По мере развития интернет-систем одни web API устаревают, как, например, SOAP (Simple Object Access Protocol), а другие пользуются большим спросом, как, например, REST (Representational state transfer). А также можно встретить и “тёмную лошадку” GraphQL, которую запустил Facebook в 2015 году. Ниже приведены схемы веб-сервисов API.
Рис 1. REST веб сервис
Рис 2. GraphQL веб сервис
Обзор возможных путей решения для REST-архитектуры
Наладить согласованную коммуникацию между всеми видами клиентов и серверным приложением бывает непросто. Отчасти эта проблема решается базовыми положениями REST архитектуры (или любой другой архитектурой, которую вы выберете), тем не менее без описания интерфейса сервера (API) не обойтись. Другими словами, разработчики клиентских приложений должны каким-то образом понимать, как им можно взаимодействовать с серверным приложением, какое это окажет влияние и что они получат в результате.
Список спецификаций для документации RESTful API:
Решением вышеперечисленных трудностей при документировании API может стать генерация автодокументации, т.е. при изменении кода приложения документация автоматически перестраивается с учетом этих изменений. Таким образом, устраняется и человеческий фактор, и проблема неактуальности. Конечно, этот способ требует определенных затрат на начальном этапе. Необходимо настроить систему генерации API-документации, а также разработать и придерживаться набора правил при написании кода.
Кейс TQM Systems: решаем задачу документации REST API
При разработке собственных веб-сервисов и при столкновении с подобными проблемами в документировании API наши разработчики нашли интересное решение, описанное далее. Итак, каким образом мы выполнили документирование REST API?
При разработке веб-приложений мы используем подход REST для реализации серверной части приложения. Этот подход позволяет легко добавлять новые виды клиентских приложений, которые должны работать с основной бизнес-логикой приложения. Например, на начальном этапе можно ограничиться использованием браузера в качестве платформы для реализации пользовательского интерфейса, а в дальнейшем добавить приложения для смартфонов или настольных компьютеров под управлением различных операционных систем. А так как концепция IoT (Internet of Things или Интернет вещей) набирает обороты, то клиентом нашего приложения может быть не только человек, но и любое устройство. Вероятность того, что придется переписывать все из-за того, что пользователи стали предпочитать одну мобильную платформу другой, значительно уменьшается. Теперь достаточно реализовать клиента для новой платформы. Не надо тратить ресурсы на переработку основного функционала, который уже протестирован и хорошо работает.
Как документировать REST API
Пример готовой документации API
В результате получилась вот такая веб-страница с описанием API.
Рис. 3 Пример Рис. 3 Пример документации API, сгенерированный библиотекой Swashbuckle.
Это не просто страница, описывающая API, она также дает возможность протестировать работу API без использования сторонних средств.
Рис 4. Web API Рис. 4 Web API документация с выводом результата работы API
Приведенная выше в качестве примера документация web API демонстрирует, что даже в стадии разработки она уже пригодна для внутреннего использования. Ее наличие значительно упростило взаимодействие между командами, которые разрабатывают серверное и клиентское приложения. После добавления описаний работы методов и форматов возвращаемых значений ее можно будет применять и для внешнего использования.
Документирование API в Java приложении с помощью Swagger и OpenAPI 3.0
Веб-приложение часто содержит API для взаимодействия с ним. Документирование API позволит клиентам быстрее понять, как использовать ваши сервисы. Если API закрыт от внешнего мира, то все равно стоит уделить время спецификации — это поможет вашим новым коллегам быстрее разобраться с системой.
Создание документации вручную — утомительный процесс. Swagger поможет вам упростить эту работу.
Что такое Swagger?
Swagger автоматически генерирует документацию API в виде json. А проект Springdoc создаст удобный UI для визуализации. Вы не только сможете просматривать документацию, но и отправлять запросы, и получать ответы.
Также возможно сгенерировать непосредственно клиента или сервер по спецификации API Swagger, для этого нужен генератор кода Swagger-Codegen.
Swagger использует декларативный подход, все как мы любим. Размечаете аннотациями методы, параметры, DTO.
Вы найдете все примеры представленные тут в моем репозитории.
Создание REST API
Чтобы документировать API, для начала напишем его 🙂 Вы можете перейти к следующей главе, чтобы не тратить время.
Добавим примитивные контроллеры и одно DTO. Суть нашей системы — программа лояльности пользователей.
Для наших примеров достаточно слоя контроллеров, поэтому я позволю себе вольность опустить серверный и репозиторный слой и добавить бизнес логику в контроллер. В своих проектах старайтесь так не делать.
В качестве DTO у нас будет класс UserDto — это пользователь нашей системы. У него пять полей, из которых 3 обязательны: имя, уникальный ключ, пол пользователя, количество баллов, дата регистрации
UserController отвечает за добавление, обновление и получение пользователей.
PointContoller отвечает за взаимодействие с баллами пользователя. Один метод этого контроллера отвечает за добавление и удаление балов пользователям.
Метод destroy в SecretContoller может удалить всех пользователей.
Настраиваем Swagger
Теперь добавим Swagger в наш проект. Для этого добавьте следующие зависимости в проект.
Swagger автоматически находит список всех контроллеров, определенных в нашем приложении. При нажатии на любой из них будут перечислены допустимые методы HTTP (DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT).
Для каждого метода доступные следующие данные: статус ответа, тип содержимого и список параметров.
Поэтому после добавления зависимостей, у нас уже есть документация. Чтобы убедиться в этом, переходим по адресу: localhost:8080/swagger-ui.html
Также можно вызвать каждый метод с помощью пользовательского интерфейса. Откроем метод добавления пользователей.
Пока у нас не очень информативная документация. Давайте исправим это.
Для начала создадим класс конфигурации сваггера SwaggerConfig — имя произвольное.
Эти данные больше для визуальной красоты UI документации.
Добавление авторов
Добавьте разработчиков API, чтобы было понятно, кто в ответе за это безобразие
Разметка контроллеров
Скрыть контроллер
Аннотация скрывает контроллер только из Swagger. Он все также доступен для вызова. Используйте другие методы для защиты вашего API.
Наша документация стала намного понятнее, но давайте добавим описания для каждого метода контроллера.
Разметка методов
Аннотация @Operation описывает возможности методов контроллера. Достаточно определить следующие значения:
Разметка переменных метода
При помощи аннотации Parameter также опишем переменные в методе, который отвечает за управление баллами пользователей.
С помощью параметра required можно задать обязательные поля для запроса. По умолчанию все поля необязательные.
Разметка DTO
Разработчики стараются называть переменные в классе понятными именами, но не всегда это помогает. Вы можете дать человеко-понятное описание самой DTO и ее переменным с помощью аннотации @Schema
Сваггер заполнит переменные, формат которых он понимает: enum, даты. Но если некоторые поля DTO имеют специфичный формат, то помогите разработчикам добавив пример.
Выглядеть это будет так:
Но подождите, зачем мы передаем дату регистрации. Да и уникальный ключ чаще всего будет задаваться сервером. Скроем эти поля из swagger с помощью параметра Schema.AccessMode.READ_ONLY :
Валидация
Подробнее о валидации данных в этой статье.
И все это нам не стоило ни малейшего дополнительного усилия.
Этих знаний вам хватит, чтобы сделать хорошее описание API вашего проекта.
Если нужны более тонкие настройки, то вы без труда сможете разобраться открыв документацию к аннотациям сваггера.
5+1 случай, когда спецификация REST API играет огромную роль
В этой статье речь пойдёт о написании и поддержке полезной и актуальной спецификации для REST API-проекта, которая позволит сэкономить много лишнего кода, а также серьёзно улучшить целостность, надежность и прозрачность прокта в целом.
Что такое RESTful API?
Серьёзно, если вы думаете, что в вашем проекте RESTful API, вы почти наверняка ошибаетесь. Идея RESTful — в построении API, который во всём соответствовал бы архитектурным правилам и ограничениям, описанным стилем REST, однако в реальных условиях это оказывается почти невозможно.
С одной стороны REST содержит слишком много расплывчатых и неоднозначных определений. Например, некоторые термины из словарей HTTP методов и статус-кодов на практике используются не по прямому назначению, при этом многие из них не используются вообще.
C другой стороны REST создаёт слишком много ограничений. К примеру, атомарное использование ресурсов в реальном мире не рационально для API, используемых мобильными приложениями. Полный отказ от хранения состояния между запросами — по сути запрет используемого во многих API механизма пользовательских сессий.
Но подождите, не всё так плохо!
Зачем нужна спецификация REST API?
Несмотря на эти недостатки при разумном подходе REST всё же остаётся отличной основой для проектирования действительно крутых API. Такой API должен иметь внутреннее единообразие, чёткую структуру, удобную документацию и хорошее покрытие unit-тестами. Всего этого можно достичь, разработав качественную спецификацию для вашего API.
Чаще всего спецификация REST API ассоциируется с его документацией. В отличие от перво (которая является формальным описанием вашего API), документация предназначена для чтения людьми: например, разработчиками мобильного или веб-приложения, использующего ваш API.
Однако, кроме собственно создания документации, правильное описание API может принести ещё очень много пользы. В статье я хочу поделиться примерами того, как с помощью грамотного использования спецификации вы сможете:
OpenAPI
Общепринятым форматом для описания REST API на сегодняшний день является OpenAPI, который также известен как Swagger. Эта спецификация представляет из себя единый файл в формате JSON или YAML, состоящий из трёх разделов:
У OpenAPI есть серьёзный недостаток — сложность структуры и, зачастую, избыточность. Для небольшого проекта содержимое JSON-файла спецификации может быстро разрастись до нескольких тысяч строк. В таком виде поддерживать этот файл вручную невозможно. Это — серьёзная угроза для самой идеи поддержания актуальной спецификации по мере развития API.
Существует множество визуальных редакторов, позволяющих описывать API и формирующих в итоге спецификацию OpenAPI. На них в свою очередь основаны дополнительные сервисы и облачные решения, например сам Swagger, Apiary, Stoplight, Restlet и другие.
Однако, для меня подобные сервисы оказались не слишком удобными из-за сложности быстрого редактирования спецификации и совмещения с процессом написания кода. Ещё один минус — зависимость от набора функций каждого конкретного сервиса. Например, реализовать полноценное unit-тестирование только средствами облачного сервиса практически невозможно. Кодогенерация и даже создание «заглушек» для эндпоинтов, хоть и кажутся весьма возможными, на практике оказываются практически бесполезными.
Tinyspec
В этой статье я буду использовать примеры на основе собственного формата описания REST API — tinyspec. Формат представляет из себя небольшие файлы, которые интуитивно понятным синтаксисом описывают эндпоинты и модели данных, используемые в проекте. Файлы хранятся рядом с кодом, что позволяет сверяться с ними и редактировать их прямо в процессе его написания. При этом tinyspec автоматически компилируется в полноценный OpenAPI, который можно сразу же использовать в проекте. Пришло время рассказать, как именно.
В статье я буду приводить примеры из Node.js (koa, express) и Ruby on Rails, хотя эти практики применимы к большинству технологий, включая Python, PHP и Java.
Когда ещё спецификация оказывается невероятно полезной
1. Unit-тесты эндпоинтов
Behavior-driven development (BDD) идеально подходит для разработки REST API. Удобнее всего писать unit-тесты не для отдельных классов, моделей и контроллеров, а для конкретных эндпоинтов. В каждом тесте вы эмулируете настоящий HTTP-запрос и проверяете ответ сервера. В Node.js для эмуляции тестовых запросов есть supertest и chai-http, в Ruby on Rails — airborne.
Вот так будет выглядеть наш тест:
Node.js
Ruby on Rails
Когда у нас есть спецификация, в которой описаны форматы ответа сервера, мы можем упростить тест и просто проверять ответ на соответствие этой спецификации. Для этого мы воспользуемся тем, что наши tinyspec-модели превращаются в OpenAPI-определения, которые в свою очередь соответствуют формату JSON Schema.
Любой literal object в JS (или Hash в Ruby, dict в Python, ассоциативный массив в PHP и даже Map в Java) можно протестировать на соответствие JSON-схеме. И даже есть соответствующие плагины для тестирующих фреймворков, например jest-ajv (npm), chai-ajv-json-schema (npm) и json_matchers (rubygem) для RSpec.
Перед тем как использовать схемы, надо подключить их в проект. Для начала сгенерируем на основе tinyspec файл спецификации openapi.json (это действие можно автоматически выполнять перед каждым запуском тестов):
Node.js
Ruby on Rails
После этого наш тест мы сможем написать так:
Обратите внимание: писать тесты подобным образом невероятно удобно. Особенно, если ваш IDE поддерживает запуск тестов и отладку (как, например, WebStorm, RubyMine и Visual Studio). Таким образом, вы можете вообще не использовать какое-либо другое ПО, а весь цикл разработки API сводится к 3 последовательным шагам:
2. Валидация входных данных
OpenAPI описывает формат не только ответов, но и входных данных. Это позволяет нам прямо во время запроса производить валидацию данных, пришедших от пользователя.
Предположим, у нас есть следующая спецификация, которая описывает обновление данных пользователя, а также все доступные для изменения поля:
Ранее мы рассматривали плагины для валидации внутри тестов, однако для более общих случаев существуют модули валидации ajv (npm) и json-schema (rubygem), давайте воспользуемся ими и напишем контроллер с валидацией.
Node.js (Koa)
Это пример для Koa — преемника Express, однако для Express код будет выглядеть похожим образом.
Добавим описание модели FieldsValidationError в файле error.models.tinyspec:
А теперь укажем её как один из возможных ответов нашего эндпоинта:
Такой подход позволит писать unit-тесты, проверяющие правильность формирования ошибки при некорректных данных, пришедших от клиента.
3. Сериализация моделей
Практически все современные серверные фреймворки так или иначе используют ORM. Это означает, что большинство ресурсов, используемых в API, внутри системы представлены в виде моделей, их экземпляров и коллекций.
Процесс формирования JSON-представления этих сущностей для передачи в ответе API называется сериализацией. Существует ряд плагинов для разных фреймворков, выполняющих функции сериализатора, например: sequelize-to-json (npm), acts_as_api (rubygem), jsonapi-rails (rubygem). По факту эти плагины позволяют для конкретной модели указать список полей, которые необходимо включить в JSON-объект, а также дополнительные правила, например для их переименования или динамического вычисления значений.
Сложности начинаются, когда нам необходимо иметь несколько отличающихся JSON-представлений одной модели или когда объект содержит вложенные сущности — ассоциации. Возникает необходимость в наследовании, переиспользовании и связывании сериализаторов.
Разные модули решают эти задачи по-разному, но давайте задумаемся, а может ли нам снова помочь спецификация? Ведь по сути вся информация о требованиях к JSON-представлениям, все возможные комбинации полей, включая вложенные сущности, уже находятся в ней. А значит мы можем написать автоматический сериализатор.
Предлагаю вашему вниманию небольшой модуль sequelize-serialize (npm), позволяющий сделать это для моделей Sequelize. Он принимает на вход экземпляр модели или массив, а также требуемую схему и итеративно строит сериализованный объект, учитывая все требуемые поля и используя вложенные схемы для ассоциированных сущностей.
Итак, предположим, у нас есть необходимость вернуть из API всех пользователей, у которых есть посты в блоге, включая комментарии к этим постам. Опишем это с помощью следующей спецификации:
Теперь мы можем построить запрос с помощью Sequelize и вернуть сериализованный объект, в точности соответствующий только что описанной выше спецификации:
Это почти магия, правда?
4. Статическая типизация
Если вы настолько круты, что используете TypeScript или Flow, возможно, вы уже задались вопросом «А как же мои дорогие статические типы?!». С помощью модулей sw2dts или swagger-to-flowtype можно сгенерировать все необходимые определения на основе JSON-схем и использовать для статической типизации тестов, входных данных и сериализаторов.
Теперь мы можем использовать типы в контроллерах:
Обратите внимание, что сгенерированные определения типов могут быть использованы не только в самом проекте API, но и в проектах клиентских приложений для описания типов функций, в которых происходит работа с API. Разработчики клиентов на Angular будут особенно рады такому подарку.
5. Приведение типов query string
То же самое касается и query-параметров (например, в GET-запросах). В этом случае веб-сервер не сможет автоматически распознать типы — все данные будут в виде строк (вот обсуждение в репозитории npm-модуля qs), так что после парсинга вы получите такой объект:
В этом случае запрос не будет проходить валидацию по схеме, а значит необходимо будет вручную убедиться, что каждый параметр имеет корректный формат, и привести его к требуемому типу.
Как нетрудно догадаться, это можно сделать с помощью всё тех же схем из нашей спецификации. Представим, что у нас есть такой эндпоинт и схема:
Вот пример запроса к такому эндпоинту
Обратите внимание, как из четырёх строк кода эндпоинта, в трёх используются схемы из спецификации.
Лучшие практики
Отдельные схемы для создания и изменения
Старайтесь не использовать одни и те же схемы для разных типов действий, чтобы избежать случайных проблем с безопасностью из-за повторного использования или наследования старых схем.
Семантика в названиях схем
Содержимое одних и тех же моделей может отличаться в разных эндпоинтах. Используйте постфиксы With* и For* в названиях схем, чтобы показать, чем они отличаются и для чего предназначены. В tinyspec модели также можно наследовать друг от друга. Например:
Постфиксы можно варьировать и комбинировать. Главное, чтобы их название отражало суть и упрощало знакомство с документацией.
Разделение эндпоинтов по типу клиента
Часто одни и те же эндпоинты возвращают разные данные в зависимости от типа клиента или роли пользователя, обращающегося к эндпоинту. Например, эндпоинты GET /users и GET /messages могут сильно отличаться для пользователей вашего мобильного приложения и для менеджеров бэк-офиса. При этом изменение самого названия эндпоинта может быть слишком большим усложнением.
Чтобы описать один и тот же эндпоинт несколько раз, можно добавить его тип в скобках после пути. Кроме того полезно использовать теги: это поможет разделить документацию ваших эндпоинтов на группы, каждая из которых будет предназначена для определённой группы клиентов вашего API. Например:
Документация REST API
После того как у вас появилась спецификация в формате tinyspec или OpenAPI, вы можете сгенерировать красивую документацию в HTML и опубликовать её на радость разработчикам, использующим ваш API.
Кроме упомянутых ранее облачных сервисов, существуют CLI-инструменты, конвертирующие OpenAPI 2.0 в HTML и PDF, после чего вы можете загрузить его на любой статический хостинг. Примеры:
Знаете ещё примеры? Поделитесь ими в комментариях.
К сожалению, вышедшая год назад OpenAPI 3.0 всё ещё мало поддерживается и мне не удалось найти достойных примеров документации на её основе: ни среди облачных решений, ни среди CLI-инструментов. По этой же причине OpenAPI 3.0 пока не поддерживается в tinyspec.
Публикация в GitHub
Один из самых простых способов публикации документации — GitHub Pages. Просто включите поддержку статических страниц для директории /docs в настройках вашего репозитория и храните HTML-документацию в этой папке.
Можно добавить команду для генерации документации через tinyspec или другой CLI-инструмент в scripts в package.json и обновлять документацию при каждом коммите:
Continuous Integration
Tinyspec Cloud
Если вам понравился синтаксис tinyspec, вы можете зарегистрироваться в качестве early adopter на tinyspec.cloud. Мы собираемся построить на его основе облачный сервис и CLI для автоматической публикации документации с широким выбором шаблонов и возможностью разрабатывать свои собственные шаблоны.
Заключение
Разработка REST API — пожалуй, самое приятное занятие из всех, что существуют в процессе работы над современными веб- и мобильными сервисами. Здесь нет зоопарка браузеров, операционных систем и размеров экранов, всё находится полностью под нашим контролем — «на кончиках пальцев».
Поддержание актуальной спецификации и бонусы в виде различных автоматизаций, которые при этом предоставляются, делают этот процесс ещё приятнее. Такой API становится структурированным, прозрачным и надежным.
Ведь по сути, если уж мы и занимаемся тем, что создаём миф, то почему бы нам не сделать его прекрасным?










