Программный интерфейс приложения или API (Application Programming Interface) обеспечивает взаимодействие между двумя системами и позволяет через Веб-интерфейс обмениваться данными между клиентом, который посылает запрос, и сервисов, который отвечает на запрос.
Существует четыре различных способа работы API: SOAP, RPC, Websocket и REST, из которых последний REST API является наиболее популярным на сегодняшний день. REST (Representational State Transfer) использует HTTP в качестве протокола передачи данных для запросов и ответов. REST API в совокупности является больше архитектурным стилем, а не стандартом написания собственных сервисов. Тем не менее разработано несколько спецификаций REST API, из которых к самым популярным относят: OpenAPI, RAML и API Blueprint. В этой статье будет разбираться OpenAPI Specification.
OpenAPI спецификация (OAS, от OpenAPI Specification) определяет формализованный стандарт, который описывает интерфейс к REST API сервису и позволяет определять возможности REST-сервиса без доступа к его исходному коду или документации. Так как спецификация не зависит от выбора языка программирования, то, следовательно, является удобной в использовании как человеком, так и машиной.
Одним из способов взаимодействия Агента ПОДД с другими системами через СМЭВ4 является использование регламентированных REST-запросов, которые описываются посредством разработки и регистрации ИС поставщиком OAS в СМЭВ4 с дальнейшим его использованием ИС потребителя.
Полное описание формата разработки спецификации OAS можно найти на официальном сайте OpenAPI Specification. В текущей статье будут описаны основные особенности и рекомендации к написанию собственной спецификации OpenAPI для разработанной системы и в качестве примера спецификация будет описана для REST-сервиса, который будет выдавать информацию о регионах РФ.
Формат спецификации
Сам документ OAS представляет собой JSON объект, который может быть представлен в формате текстового файла JSON или YAML, последнее является более строгим и компактным синтаксисом JSON объекта. Все ниже приведенные примеры будут в формате JSON, так как конечный результат спецификации необходимо представить именно в таком стиле. Сам же сайт Swagger предоставляет веб-интерфейс для написания и редактирования OAS в формате YAML с последующей возможностью экспорта спецификации в JSON формат.
К основным терминам представления данных в формате JSON относят определения имени поля и его значение. Например, поле с именем field имеет числовое значение 3.0, как в следующем примере:
{"field": 3.0 } |
Стоит учитывать, что все имена полей в спецификации чувствительны к регистру. При этом стандарт спецификации OAS определяет два типа полей: это фиксированные или заранее определенные спецификацией имена полей, которые будут разобраны ниже и собственные имена полей, которые будут играть важную роль при использовании составленной спецификации (рекомендуется использовать строго латинские буквы).
Версия
Рекомендуемой версией к использованию спецификации является OpenAPI 3.0, которая значительно отличается от версии 2.0. Версия конкретной спецификации определяется полем openapi в начале каждого OAS документа.
Типы данных
К основным типам данных в OAS относят: integer, number, string и boolean. Типы данных так же имеют опциональное свойство формат, которое определяет более детальную информацию о типе.
Основная информация
Каждая написанная спецификация должна содержать в себе небольшой раздел метаданных в поле с названием info, которое будет описывать наименование, описание и версию конкретного документа.
{"title": "Регионы РФ", "description": "Информация о регионах Российской Федерации", "version": "1.0.0" } |
Компоненты
Не мало важной частью любой спецификации OpenAPI являются компоненты, которые описываются в поле с названием components в подразделе объекта shcemas. Под компонентами понимаются многократно переиспользуемые объекты для разных аспектов всей спецификации. Сами по себе компоненты не имеют никакого влияния на REST API интерфейс до тех пор, пока к ним явно не указано обращение из другой части документа.
В качестве компонента можно написать простую модель, которая будет описывать основные данные о регионе РФ. К таким данным отнесем уникальное значение записи (идентификатор), наименование, код региона и его краткое описание. Дополнительно укажем особо важные к заполнению параметры через required.
{ "components": {
"schemas": {
"Region": {
"required": [
"code",
"id",
"name"
],
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"code": {
"type": "integer"
},
"about": {
"type": "string"
}
}
}
}
}
}
|
Адреса
Прежде чем перейти к финальной части написания документа спецификации, стоит разобрать структуру итогового URL-запроса, по которому будет происходить обращение к OAS некоторого ИС поставщика.
Состоит такой запрос в первую очередь из сетевого адреса установленного Агента ПОДД, порта обращения к OpenAPI ПОДД, мнемоники ИС, которая обрабатывает запросы по собственной спецификации OpenAPI, заданного пути для обращения к сервису согласно заявки на регистрацию OAS и полной относительной части URL адреса, который описывается в спецификации.
| {protocol}://{einfahrt}:{port}/{is_mnemonic}/{base_path}/{relative_path} |
Все относительные части запроса описываются в поле с именем paths. Такие запросы отделены друг от друга уникальным собственным именем поля, которое начинается с прямого слеша. В таком объекте описываются все возможные HTTP методы (GET, POST, PUT, DELETE и др.) и они содержат описательные характеристики и особенности составления такого обращения. Следующая часть является примером описания относительной части GET запроса для получения записи о регионе РФ по идентификатору.
{ "/region/{id}": {
"get": {
"operationId": "regionById",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"style": "simple",
"explode": false,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "Информация о регионе РФ",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Region"
}
}
}
},
"422": {
"description": "Ошибка создания"
}
}
}
}
}
|
Стоит отметить важный параметр operationId в описании запроса, по которому ПОДД определяет уникальность каждого обращения к ИС поставщику.
По вышеизложенному примеру относительной части запроса, можно составить следующий URL адрес для ИС поставщика с мнемоникой MNEMONIC и заданного пути обращения mainPath:
http://localhost:8171/MNEMONIC/mainPath/region/1
Итоговая спецификация
В спецификацию можно добавить сколько угодно относительных адресов обращения к REST сервису и разбивать составляющие запросов на удобное количество компонентов. По результату написания спецификации можно увидеть следующий небольшой документ всего с тремя обращениями.
{ "openapi": "3.0.0",
"info": {
"title": "Регионы РФ",
"description": "Информация о регионах Российской Федерации",
"version": "1.0"
},
"paths": {
"/region": {
"post": {
"operationId": "regionCreate",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RegionPost"
}
}
}
},
"responses": {
"200": {
"description": "Данные о созданном регионе",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Region"
}
}
}
},
"422": {
"description": "Ошибка создания"
}
}
}
},
"/region/{id}": {
"get": {
"operationId": "regionById",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"style": "simple",
"explode": false,
"schema": {
"type": "integer"
}
}
],
"responses": {
"200": {
"description": "Информация о регионе РФ",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Region"
}
}
}
},
"422": {
"description": "Ошибка создания"
}
}
}
},
"/regions": {
"get": {
"operationId": "regionsAll",
"responses": {
"200": {
"description": "Данные о регионах",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Region"
}
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Region": {
"required": [
"code",
"id",
"name"
],
"type": "object",
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"code": {
"type": "integer"
},
"about": {
"type": "string"
}
}
},
"RegionPost": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"code": {
"type": "integer"
},
"about": {
"type": "string"
}
}
}
}
}
}
|