REST API: Вопросы, которые стоит задать

03.09.25

Интеграция - WEB-интеграция

В профильных чатах или на форумах возникают жаркие споры о тонкостях проектирования REST API. Однако часто упускается вопрос, зачем мы уделяем этому внимание и пытаемся проектировать «правильное REST API». Обсудим, что такое REST, почему в большинстве случаев оно не нужно, и почему этот стиль такой популярный.

Меня зовут Данила Рачилин. Я один из разработчиков компании WiseAdvice.tech. Мы специализируемся на обслуживании и консалтинге бухгалтерских и учетных функций. В нашем контуре довольно часто встречаются различные интеграции, в большинстве случаев – это B2B-интеграции по принципу back-to-back с корпоративными системами.

Идея этой статьи появилась очень интересно. Она возникла во время одного из споров, в котором я участвовал, когда речь зашла о том, как правильно проектировать API. Ситуация старая как мир: сколько существует REST, столько и длится этот самый холивар.

Мне захотелось разобраться:

  • почему мы так стремимся «правильно» проектировать REST,

  • действительно ли мы это делаем правильно,

  • какие проблемы мы встречаем при проектировании API в стиле REST,

  • почему HTTP и REST такие, какие они есть,

  • и какие могут быть альтернативы.

Что вообще представляет собой REST? Кратко: это концепция построения сервисов, работающих поверх протокола HTTP в соответствии с определенной архитектурой.

 

Основные признаки REST

 

Можно выделить три ключевых признака, по которым мы чаще всего узнаем REST. Используются URL как идентификаторы ресурсов, HTTP-методы (глаголы) применяются по назначению, а статус-коды – корректно.

Думаю, все, кто читает эту статью, прекрасно это понимают.

Теперь давайте рассмотрим несколько примеров API и попробуем понять, какой из них действительно REST.

Первый пример. Что бросается в глаза?

 


Похоже, это не REST. Используется только один метод – POST. Глаголы действий указаны в названиях методов, а сами URL не содержат идентификаторов ресурсов.

Второй вариант. Может, это он?

 

 

Используются два метода: GET и POST – уже интереснее. Есть какая-то идентификация – например, во второй строке. Но тоже не совсем то.

Третий вариант. Он наиболее интересный.

 

 

Здесь представлено разнообразие HTTP-методов: GET, PUT, DELETE, POST. Тот самый пресловутый CRUD (или CRUDEL – Create, Read, Update, Delete, List). Это стандартные действия над ресурсами. Значит, здесь уже используются глаголы по назначению. Есть полноценная идентификация ресурсов. Со статус-кодами неясно, но пока опустим этот момент. Нас сейчас интересуют именно представления методов.

А что, если я скажу, что все три варианта, которые я показал, – это все-таки REST? Просто REST разного уровня зрелости.

Существует такая полезная штука – уровень зрелости REST (или Модель Ричардсона). Ее однажды придумали, чтобы классифицировать настоящие REST-сервисы по четырем уровням, начиная с нулевого.

 

 

Таким образом, приведенные мной примеры относятся к разным уровням зрелости REST. Но когда мы говорим REST, как правило, имеем в виду второй уровень.

 

Проблемы при проектировании REST API

 

Вокруг REST возникают постоянные холивары – они основаны на сложностях и недопонимании, с которыми мы сталкиваемся при проектировании API. Cамые частые проблемы: HTTP-методы и статус-коды плохо ложатся на сложную бизнес-логику.

Например, простой метод «получить список товаров», возвращающий массив данных, – это понятно и удобно. Но что, если речь идет о сложном процессе, например, оформлении заявки по паттерну «мастер» – когда нужно последовательно подгружать и обрабатывать данные? Тут уже возникают трудности. Кажется, что CRUD-подход перестает справляться.

Есть еще и проблема N+1: мы нагружаем систему избыточными операциями, потому что пытаемся получить множество дополнительных данных и ресурсов, хотя не всегда они нужны в таком объеме.

Эта проблема особенно проявляется при связях «один ко многим» – когда для каждого элемента приходится делать дополнительные запросы. Из этого вытекает третья проблема: избыточная нагрузка на систему, которая не всегда оправдана.

Чтобы понять, откуда берутся эти сложности, и почему REST устроен именно так, – сделаем небольшой экскурс в историю. Посмотрим, как все это зарождалось.

 

История создания HTTP и REST

 

В 1989 году протокол HTTP был разработан в CERN. Его первоначальная версия использовалась как протокол для электронной библиотеки. Изначально был только один метод – GET, который возвращал HTML-страницу. Пользователь просто «перелистывал» страницы, переходя по ссылкам.

Затем начался стремительный рост популярности World Wide Web – нашей любимой «паутины». В 1996 году вышла первая полноценная версия HTTP. А в 2000 году один из ключевых людей в мире веб-интерфейсов и интеграций – Рой Филдинг – представил диссертацию, в которой описал архитектуру REST.

В ней он говорит, что REST – это не что иное, как обоснование тех идей, которые были заложены в протокол HTTP с самого начала. Филдинг – соавтор протокола HTTP, и в своей диссертации он описывает именно те принципы, которые закладывались при его разработке, – но уже в виде четкой архитектурной концепции.

Этих принципов шесть. Они на рисунке.

 

 

 

Принципы REST: единообразие интерфейса и HATEOAS

 

Нас сейчас особенно интересует принцип единообразия интерфейса. Он включает четыре подпункта:

  1. Идентификация ресурсов – мы уже сталкивались с этим: URL выступают в роли идентификаторов объектов. Это основа REST.

  2. Работа с ресурсами через представление – речь о том, что в заголовке Content-Type мы указываем тип данных, которые передаем клиенту. Это позволяет понять формат тела ответа.

  3. Самодокументированное сообщение (Self-descriptive messages) – каждое сообщение должно содержать всю необходимую информацию для его обработки. Клиенту не нужно знать контекст заранее – все должно быть понятно из самого запроса и ответа.

  4. HATEOAS – самый интересный и редко используемый принцип. Это аббревиатура от Hypermedia as the Engine of Application State. Суть его в том, что сервер возвращает вместе с ресурсом информацию о связанных ресурсах и доступных действиях над ними.

 

 

Базовый ответ, соответствующий принципу HATEOAS, содержит поле links – массив ссылок. В нем перечислены идентификаторы ресурсов и указываются методы, которые можно к ним применить (например, GET, POST и т.д.).

 

HATEOAS и уровень зрелости REST

 

В итоге получается, что HATEOAS – это как раз то самое, что делает сервис по-настоящему RESTful. Если вернуться к диаграмме зрелости REST, то наличие HATEOAS означает достижение максимального, третьего уровня зрелости. Он подразумевает полную самодокументированность API: клиент может самостоятельно навигироваться по системе, не зная заранее все возможные endpoint’ы.

На практике, если вы используете HATEOAS, в Swagger или OpenAPI у вас появляется гораздо меньше необходимости – сам API уже «рассказывает» о себе. Мы возвращаем один endpoint, а дальше клиент ориентируется по ресурсу и связанным с ним ссылкам.

HATEOAS до сих пор существует и используется. Это действительно удобная и применимая концепция в определенных сценариях.

Как я сказал, когда мы говорим REST, мы чаще всего имеем в виду второй уровень зрелости. Третий уровень – с HATEOAS – существует, но применяется редко.

Кто-то из вас, разрабатывая интеграции, сервисы или предоставляя свой API, вообще задумывался о том, чтобы в 1С соблюдать HATEOAS? Хотя концепция применима, на практике мы чаще всего пишем back-to-back сервисы, где нет публичного клиента, которому нужна навигация по ресурсам, переходы между состояниями и прочие REST-сценарии. В таких системах задача простая: «сделай действие здесь и сейчас и верни правильный ответ».

 

Зачем вообще был нужен HATEOAS


Когда все это проектировалось, когда Рой Филдинг писал свою диссертацию, уровень систем был иным. Они ограничивались простыми CRUD-операциями, которые отлично вписывались в модель REST. Речь шла о навигации по простым медиаресурсам: страницам, изображениям, форумам, новостным статьям – всему, что можно описать через GET, PUT, DELETE, UPDATE.

Современные системы уже не такие, поэтому возникает вопрос: для чего это было нужно?

 


Кстати, примерно такое же выражение лица было у меня, когда я сам впервые разбирался во всем этом.

 

Вопросы, которые нужно задать при проектировании API

 

Когда мы проектируем свои сервисы, важно заранее задать себе несколько ключевых вопросов, чтобы потом не спорить в команде и не устраивать холивары на тему «а это вообще REST или нет».

  1. Мы разрабатываем веб-интерфейс с фронтендом, где нужна навигация по ресурсам, сложные действия над объектами – или все ограничивается простыми CRUD-операциями?

  2. Хотим ли мы упираться в рамки REST, если это усложнит логику и сделает API менее понятным?

  3. Нужно ли нам реализовывать HATEOAS?

Учитывая, что большинство наших интеграций – это back-to-back взаимодействие, вряд ли HATEOAS нам действительно нужен. Тогда возникает четвертый вопрос: а можно ли вообще отказаться от REST? Если мы не получаем от него преимуществ, зачем следовать его принципам?

Альтернативой может стать RPC-стиль проектирования API.

 

RPC-стиль: принципы и преимущества

 

На рисунке основные объективные плюсы RPC. Мы используем один URL – своего рода «универсальный исполнитель» (endpoint-executor), на который отправляются все запросы. Для всех вызовов используется один HTTP-метод – POST. Мы не тратим время на выбор глагола, не переживаем за статус-коды.

Параметры и название метода передаются в теле запроса как служебные поля.

Таким образом, на один endpoint приходится множество методов. На все запросы возвращаем HTTP 200 OK, а логику статуса переносим внутрь тела ответа.

Среди преимуществ – сама концепция RPC (Remote Procedure Call), которая означает «вызов удаленной процедуры». Мы не ограничиваем себя глаголами, а просто вызываем нужную функцию – как привыкли в 1С: вызвали общий модуль, передали параметры, получили результат и пошли дальше.

 

Пример RPC-запроса и его особенности

 

Когда мы проектируем back-to-back сервисы для корпоративных интеграций, все чаще оказывается, что HATEOAS нам не нужен.

Нам не требуется навигация по ресурсам – нужно просто вызвать удаленную процедуру, передать данные, получить валидный ответ и идти пить чай.

Рассмотрим пример типичного RPC-запроса.

 

 

Как я уже говорил, используется один HTTP-метод – POST – и один общий endpoint, например, /command.

В теле запроса передаются:

  • служебное поле version – для версионирования API;

  • method – название вызываемого метода;

  • params – структура параметров, например, объект product.

Ответ выглядит аналогично: поле result содержит данные результата, а статус обработки можно передать внутри тела.

 

 

Мы можем всегда возвращать HTTP 200 OK, а свою семантику ошибок и статусов реализовать на уровне приложения. Нам не обязательно использовать 201, 404 или другие HTTP-коды – мы не привязываемся к их строгой семантике.

Более того, RPC-стиль не зависит от транспорта. В отличие от REST, который неразрывно связан с HTTP (потому что Рой Филдинг, будучи соавтором HTTP, строил REST вокруг его возможностей), RPC может работать поверх разных протоколов: HTTP, WebSockets, gRPC, message brokers и других.
Это дает гибкость на будущее.

 

Недостатки RPC-стиля

 

Однако у RPC есть и обратная сторона: он лишен некоторых преимуществ, которые дает REST. Речь о таких вещах, как кэширование, маршрутизация, балансировка нагрузки и мониторинг. Когда все запросы идут на один endpoint – гибкость снижается. Да, масштабирование и развитие идут быстро: добавил метод – и готово. Не нужно каждый раз проектировать сложные URI или думать, какой HTTP-метод использовать. Но именно в этом и кроется подвох.

Один универсальный обработчик может превратиться в «черный ящик», который становится сложно обслуживать по мере роста числа методов. Появляется проблема с кэшированием: POST-запросы по умолчанию не кэшируются, потому что они неидемпотентны. Сервер всегда возвращает свежий ответ, что создает избыточную нагрузку. Маршрутизация и балансировка тоже усложняются. Все запросы приходят на один адрес – и если их много, можно исчерпать лимит входящих соединений на веб-сервере.

Если бы у нас было несколько отдельных сервисов, мы могли бы распределить их по разным пулам, снизив нагрузку.

Мониторинг – еще одна сложность. Но ее можно решить: если в строке запроса есть параметр URI method, мы можем логировать его на уровне веб-сервера. Тогда, даже не читая тело, сможем понять, какие методы вызываются чаще, где растет нагрузка.

То есть все проблемы решаемы, но требуют дополнительных усилий – в отличие от REST, где многие из них решаются «из коробки».

 

Гибриды и практика: REST + RPC

 

Исходя из этого, появляются более гибкие и практичные подходы. Мы – разработчики, и наша фантазия бьет ключом. Мы не обязаны слепо следовать каким-то стандартам, если они ухудшают нашу систему. Поэтому на практике часто возникают гибриды REST и RPC. Например, используются GET и POST для базовых операций, а сложные действия – через RPC-подобные вызовы на отдельных endpoint’ах. Такой подход имеет право на жизнь.

 

 

Кстати, мы всегда смотрим на вендора. У него много удачных решений, которые мы с успехом перенимаем. На мой взгляд, одно из самых технологичных – облачная подсистема Fresh, где разработчики поняли: «REST – это не догма». Они осознали, что их системы будут взаимодействовать с разными внешними системами и выбрали подход, который лучше всего подходит под задачу.

 

Пример от вендора: Fresh и Extended API

 

Уточню немного контекст. FRESH – это облачная платформа, которая работает на основе механизма разделения данных в одной информационной базе. Для тех, кто не в курсе: в одной информационной базе может быть несколько областей – по сути, несколько независимых информационных баз, объединенных в единую инфраструктуру. FRESH – это комплекс программных продуктов, основным из которых является менеджер сервиса, управляющая конфигурация всей этой системы.

Для внешнего управления инфраструктурой вендор реализовал API, в котором применил RPC-стиль взаимодействия – он называется Extended API. По ссылке https://its.1c.ru/db/freshsm можно перейти в документацию ИТС, посмотреть, как устроен подход и как все это выглядит на практике.

 

 

На рисунке – скриншот из конфигурации: там есть обработка методов ExtAPI, где описаны все доступные вызовы. Это позволяет наглядно показать, как устроено API и какие элементы используются.

Мы видим, что в выделенной зеленой части находятся данные бизнес-логики – параметры методов. Красным цветом выделены служебные поля: например, version – для версионирования API. Есть также режим отладки – debugMode. Эти поля не строго фиксированы, внутри команды нужно договориться, какие поля использовать и как их интерпретировать.

В самой нижней части – ответ, который возвращается. Он тоже состоит из регламентированных полей, согласованных при проектировании. Это responseCode – код возврата, который, если посмотреть справа, отличается от HTTP. Но при этом взяты за основу стандартные HTTP-коды: например, 10200.
Первые две цифры добавлены к классическим кодам – видимо, для расширения семантики ошибок.

Есть поле error – флаг ошибки, и message – текстовое описание. Все понятно и прозрачно. А выше – сам обработчик метода. По сути, это и есть вся «магия»: название метода, например, srvFile.isCompleteMultipart, напрямую связано с вызовом удаленной процедуры в ядре. Вся архитектура Extended API построена примерно так. Это лишь малая часть, но она показательна.

При этом вендор не следует REST слепо. Где уместно – использует CRUD: в названиях методов встречаются create, delete, list. Где это неудобно, нелогично или неуместно – спокойно отходит от паттернов: например, newPart, newMultipart. И при этом все работает стабильно.

 

 

Почему это так сделано? В менеджере сервиса очень много разных интерфейсов, которые сильно отличаются друг от друга. Если на каждый «навешивать» REST, который там малоприменим, это только усложнит и замедлит интеграцию. Гибкость важнее догм.

 

Заключение: REST – не догма

 

В завершение хотелось бы сказать, что REST – это не свод непреложных законов, которые нужно слепо и бездумно соблюдать. При проектировании API важно вместе с командой понимать зачем мы его делаем, какие у нас требования и какие могут быть подводные камни. Например:

  • Хотим ли мы в будущем сменить транспорт – перейти с HTTP на WebSockets, message brokers и т.п.? Тогда, возможно, стоит изначально закладываться в RPC-подобную архитектуру.

  • Или у нас внешняя система с навигацией, где важна идентификация ресурсов через URL? Тогда REST подойдет идеально. Например, B2B-портал для оформления заявок от поставщиков – вот где REST действительно «садится» отлично. Там нужна навигация, самодокументированность, четкая структура.

Проектируйте удобное и понятное API, чтобы оно вас никогда не «пятисотило», а работало стабильно и предсказуемо.

 

*************

Статья написана по итогам доклада (видео), прочитанного на конференции INFOSTART TECH EVENT.

Вступайте в нашу телеграмм-группу Инфостарт

См. также

Оптовая торговля Розничная торговля WEB-интеграция 1С:Управление торговлей 10 1С:Управление производственным предприятием 1С:Управление нашей фирмой 1.6 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Платные (руб)

Онлайн-заказ - это решение для автоматизации процесса оформления заказов на сайте в торговых организациях. Продукт обеспечивает легкое взаимодействие между компанией и клиентами через веб-интерфейс, интегрированный с 1С:Предприятие. Система позволяет снизить операционные расходы, повысить лояльность клиентов и оптимизировать работу отдела продаж.

57600 руб.

26.11.2024    6457    4    3    

7

Сайты и интернет-магазины WEB-интеграция Системный администратор Программист Пользователь 1С v8.3 1C:Бухгалтерия 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    21550    30    24    

24

SALE! 15%

WEB-интеграция Программист Бизнес-аналитик 1С v8.3 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Оптовая торговля, дистрибуция, логистика ИТ-компания Платные (руб)

Модуль "Экспортер" — это расширение для 1С, предназначенное для автоматизации процессов выгрузки данных. Оно позволяет эффективно извлекать, преобразовывать и передавать данные из систем 1С в интеграционную платформу Spot2D. Подсистема упрощает настройку, снижает количество ручных операций и обеспечивает удобный контроль данных.

17280 14688 руб.

20.12.2024    3773    18    2    

20

WEB-интеграция Программист Руководитель проекта 1С v8.3 1C:Бухгалтерия 1С:Франчайзи, автоматизация бизнеса Платные (руб)

Расширение значительно упрощает написание API на 1С. Веб программисты получают простой и понятный доступ к 1С. Описание API создаётся автоматически и представляется в виде удобном как для человека, так и для программной обработки. Основные преимущества: 1. Документация API создаётся автоматически. Удобна для программной обработки. 2. Изменить API столь же просто как настроить отчёт. Можно опубликовать существующий вариант отчёта. 3. Отчёты в API поддерживают параметры (Период, ДатаНачала и др.) 4. При создании простых методов не требуется изменять конфигурацию. 5. Поддерживается работа с планами обмена.<br/> 6. Возможно настроить отправку из 1С данных корреспондирующей системе, для случаев когда 1С сама "знает" какие данные нужно отправить. 7. После записи в 1С Ле Мурр может возвращать соответствие полученных идентификаторов созданным в 1С объектам данных.

36000 руб.

27.09.2024    8287    7    5    

9

WEB-интеграция 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Оптовая торговля, дистрибуция, логистика Россия Платные (руб)

В расширении реализован механизм интеграции между системой поставщика и Личным кабинетом СДТ. Реализован обмен заказами и реализациями (накладными), предусмотрено отслеживание статусов документов. Расширение предназначено для 1С:УТ 11.4.

35856 руб.

27.11.2024    2030    1    0    

1
Для отправки сообщения требуется регистрация/авторизация