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    5715    4    3    

7

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

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

14400 руб.

20.12.2024    3132    16    2    

17

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

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

60000 руб.

07.05.2019    38312    73    45    

31

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

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

35856 руб.

27.11.2024    1654    1    0    

1

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

Обработка является альтернативой механизму, разработанному фирмой 1С и заполняющему реквизиты контрагента по ИНН или наименованию. Не требуется действующей подписки ИТС. Вызывается как внешняя дополнительная обработка, т.е. используется, непосредственно, из карточки контрагента. Заполнение по ИНН или наименованию реквизитов контрагента по данным сайта ФНС (egrul.nalog.ru) для БП 2.0, БП 3.0, БГУ 1.0, БГУ 2.0, УТ 10.3, УТ 11.x, КА 1.1, КА 2.x, УПП 1.x, ERP 2.x, УНФ 1.5, УНФ 1.6, УНФ 3.0, ДО 2.1

3000 руб.

28.04.2016    97085    109    218    

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