Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Неудобные вопросы про RESTful, или как проектир...

Неудобные вопросы про RESTful, или как проектировать API, чтобы не было так стыдно

Когда мы работаем с Микросервисной Архитектурой, часто возникает необходимость описать коммуникацию двух сервисов. Но как это сделать правильно, чтобы API выглядело понятно для потребителей, было простым в расширении и поддержке?

Avatar for Romanov Alexey

Romanov Alexey

March 30, 2025
Tweet

More Decks by Romanov Alexey

Other Decks in Programming

Transcript

  1. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ПЛАН ДОКЛАДА Что такое RESTful API. Как применять RESTful: • что такое представление, как оно связано с доменной сущностью; • как CRUD ложится на HTTP verbs; • что такое stateless и почему это так важно в микросервисах. Пример: проектируем RESTful API для сущностей User, Address, Wallet. Описание API с помощью протокола OpenAPI. Плюсы и минусы подходов Contract first и Code first. Версионирование API. 2
  2. 12+ лет Java/Kotlin. 7+ лет в роли TeamLead/Архитектора. 6 лет

    опыт DevOps. Co-founder EdTech стартапа IT-Enduro. Работаю в роли Software Архитектора. Мы с вами встречались на других конференциях :) РОМАНОВ АЛЕКСЕЙ
  3. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ЧТО ТАКОЕ RESTFUL? 4 REST — это аббревиатура от Representational State Transfer (Передача Состояния Представления). Это согласованный набор архитектурных принципов для создания более масштабируемой и гибкой сети.
  4. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ЧТО ТАКОЕ RESTFUL? 5 Сервер содержит ресурсы и определяет операции над ними. Клиент работает с представлениями ресурсов, для изменения состояния сервера он передает желаемое представление ресурса на сервер. Это достигается за счет выполнения 4х ограничений. Определение ресурсов. Управление ресурсами через представления. Самодостаточные сообщения. Hypermedia as the Engine of Application State.
  5. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ЧТО ТАКОЕ ПРЕДСТАВЛЕНИЕ? 6 В терминологии RESTful ресурс – это информация, которую различные приложения предоставляют своим клиентам. Каждый ресурс должен иметь постоянный уникальный идентификатор. Управление ресурсами через представления – клиент управляет ресурсами, направляя серверу данные, обычно в виде JSON, содержащие представление, который он хотел бы добавить, удалить или изменить. Когда клиент хочет внести изменения в ресурсы, он посылает серверу представление того, каким он видит итоговый ресурс. Сервер принимает запрос как предложение, но за ним всё так же остаётся полный контроль.
  6. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 CRUD МЕТОДЫ НА БАЗЕ HTTP 7 Методы HTTP (глаголы) составляют основную часть «единого интерфейса», ограничивающего и предоставляющего возможность осуществлять действия над существительным-ресурсом. НАЗВАНИЕ Описание POST Создание новых ресурсов. При успешном создании ресурса возвращается HTTP код 201, а также в заголовке «Location» передается адрес созданного ресурса. GET Получение представления ресурса. Запрос используется только для чтения данных, менять с помощью него состояние нельзя. PUT Полное обновление или создание ресурса. В отличие от POST, PUT метод передает ID ресурса, выбранного клиентом. PATCH Изменение представления существующего ресурса по ID. Возможна передача не полного представления, а только полей, которые требуется изменить. DELETE Используется для удаления ресурса, идентифицированного конкретным ID. C D R U
  7. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 STATELESS 8 Отсутствие состояния (Stateless) подразумевает собой то, что необходимое состояние для обработки запроса содержится в самом запросе, либо в рамках URI, параметрах строки запроса, тела или заголовках. Определение URI уникально идентифицирует ресурс и тело, содержащее состояние этого ресурса. После того, как сервер завершит обработку, состояние или его часть отдается обратно клиенту через заголовки, статус и тело ответа. Клиент должен включать всю информацию для сервера 
 для выполнения запроса.
  8. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 РЕЗЮМИРУЯ 9 Фактически, RESTful – это всего лишь набор URI, HTTP вызовов к этим URI и некоторое количество представлений ресурсов в разных форматах. За основу адресации берется покрытие уникальными идентификаторами ресурсов: у каждого ресурса есть свой адрес, вся информация, которую сервер может предоставить, представлена как ресурс. Когда вы решаете, какие ресурсы буду в вашей системе, называйте их существительными, в противоположность глаголам, или действиям. Другими словами, URI должен ссылаться на ресурс, а не на действие.
  9. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ХОРОШИЙ, ПЛОХОЙ, ЗЛОЙ RESTFUL 10 Получение данных о пользователе: ПЛОХО GET /users?id=1 ХОРОШО GET /users/{id} Создание пользователя: ПЛОХО GET /users?action=create&name=… ХОРОШО POST /users body: {"name": "..."} Заблокировать пользователя: ПЛОХО GET /users?id=1&action=block ХОРОШО POST /users/{id}/block
  10. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ХОРОШИЙ, ПЛОХОЙ, ЗЛОЙ RESTFUL 11 Получение данных о заказах пользователя: НОРМАЛЬНО GET /users/{id}/orders ХОРОШО GET /orders/?userId=1 Сделать заказ от имени пользователя: НОРМАЛЬНО POST /users/{id}/orders 
 body: {"items": [...]} ХОРОШО POST /orders 
 body:{"userId": 1, "items": [...]}
  11. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ПРИМЕР: USERS, WALLETS 12
  12. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ПОЛУЧИТЬ ВСЕХ ПОЛЬЗОВАТЕЛЕЙ 13 REQUEST: GET http://localhost:8080/api/v1/users RESPONSE: 200 OK [ { "id": 1, "firstName": "Алексей", "lastName": "Романов", "age": 33, "login": "romanow", "address": 1 } ]
  13. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ПОЛУЧИТЬ ВСЕХ ПОЛЬЗОВАТЕЛЕЙ ПОСТРАНИЧНО 14 REQUEST: GET http://localhost:8080/api/v1/users?page=1&size=10 RESPONSE: 200 OK { "page": 1, "pageSize": 1, "totalElements": 1, "items": [{ "id": 1, "firstName": "Алексей", "lastName": "Романов", "age": 33, "login": "ronin", "address": 1 }] }
  14. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ПОЛУЧИТЬ ПОЛЬЗОВАТЕЛЯ ПО ID 15 REQUEST: GET http://localhost:8080/api/v1/users/1 RESPONSE: 200 OK { "id": 1, "firstName": "Алексей", "lastName": "Романов", "age": 33, "login": "ronin", "address": 1 }
  15. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 РЕДАКТИРОВАТЬ ПОЛЬЗОВАТЕЛЯ 16 REQUEST: PATCH http://localhost:8080/api/v1/users/1 Content-Type: application/json { "age": 34, "login": "romanov" } RESPONSE: 200 OK { "id": 1, "firstName": "Алексей", "lastName": "Романов", "age": 34, "login": "ronin", "address": 1 }
  16. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 УДАЛИТЬ ПОЛЬЗОВАТЕЛЯ 17 REQUEST: DELETE http://localhost:8080/api/v1/users/1 RESPONSE: 204 No Content
  17. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ПОИСК ПОЛЬЗОВАТЕЛЕЙ ПО ИМЕНИ 18 REQUEST: GET http://localhost:8080/api/v1/users? firstName=Алексей&lastName=Романов RESPONSE: 200 OK [ { "id": 1, "firstName": "Алексей", "lastName": "Романов", "age": 34, "login": "ronin", "address": 1 } ]
  18. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ПОЛУЧИТЬ СПИСОК ПОЛЬЗОВАТЕЛЕЙ ПО СПИСКУ ID 19 REQUEST: POST http://localhost:8080/api/v1/users/search Content-Type: application/json { "ids": [1, 2] } RESPONSE: 200 OK [{ "id": 1, "firstName": "Алексей", "lastName": "Романов", "age": 34, "login": "ronin", "address": 1 }]
  19. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ПОЛУЧИТЬ ПОЛЬЗОВАТЕЛЯ С АДРЕСОМ 20 REQUEST: GET http://localhost:8080/api/v1/user-with-address/1 RESPONSE: 200 OK { "id": 1, "firstName": "Алексей", "lastName": "Романов", "age": 34, "login": "ronin", "address": { "city": "Москва", "country": "Россия", "address": "Новогиреево" } }
  20. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 СОЗДАТЬ ПОЛЬЗОВАТЕЛЯ С АДРЕСОМ 21 REQUEST: POST http://localhost:8080/api/v1/users-with-address Content-Type: application/json { "firstName": "Герман", "lastName": "Дубинин", "age": 34, "login": "thething", "address": { "city": "Красногорск", "country": "Россия", "address": "Опалиха" } } RESPONSE: 201 Created Location: http://localhost:8080/api/v1/users-with-address/2
  21. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ЧАСТИЧНОЕ ОБНОВЛЕНИЕ ПОЛЬЗОВАТЕЛЯ С АДРЕСОМ 22 REQUEST: PATCH http://.../users-with-address/1 Content-Type: application/json { "login": "romanow", "address": { "city": "Красногорск", "country": "Россия", "address": "улица Геологов" } } RESPONSE: 200 OK { "id": 1, "firstName": "Алексей", "lastName": "Романов", "age": 34, "login": "romanow", "address": { "city": "Красногорск", "country": "Россия", "address": "Геологов" } }
  22. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ПОЛНОЕ ОБНОВЛЕНИЕ ПОЛЬЗОВАТЕЛЯ С АДРЕСОМ 23 REQUEST: PATCH http://.../users-with-address/3 Content-Type: application/json { "firstName": "Макс", "lastName": "Иванов", "age": 29, "login": "mommys_hacker", "address": { "city": "Москва", "country": "Россия", "address": "Тульская" } } RESPONSE: 200 OK { "id": 3, "firstName": "Макс", "lastName": "Иванов", "age": 29, "login": "mommys_hacker", "address": { "city": "Москва", "country": "Россия", "address": "Тульская" } }
  23. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ПОЛУЧИТЬ ВСЕ КОШЕЛЬКИ ПОЛЬЗОВАТЕЛЯ 24 REQUEST: GET http://localhost:8080/api/v1/users/1/wallets RESPONSE: 200 OK [{ "id": 1, "name": "Траты на велосипед", "balance": 2400.0, "hold": 0, "type": "VISA", "status": "approved" }, { "id": 2, "name": "Траты на Lego", "balance": 5700.0, "hold": 300.0, "type": "VISA", "status": "approved" }]
  24. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ДОБАВИТЬ КОШЕЛЕК ДЛЯ ПОЛЬЗОВАТЕЛЯ 25 REQUEST: POST http://localhost:8080/api/v1/users/1/wallets Content-Type: application/json { "name": "Общий", "type": "VISA" } RESPONSE: 201 CREATED Location: GET http://localhost:8080/api/v1/wallets/3
  25. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ПОЛУЧИТЬ КОШЕЛЕК ПО ID 26 REQUEST: GET http://localhost:8080/api/v1/wallets/2 RESPONSE: 200 OK { "id": 3, "name": "Общий", "balance": 0, "hold": 0, "type": "VISA", "status": "new", "user_id": 1 }
  26. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ИЗМЕНИТЬ ДАННЫЕ КОШЕЛЬКА 27 REQUEST: PATCH http://localhost:8080/api/v1/wallets/3 Content-Type: application/json { "name": "Повседневные траты" } RESPONSE: 200 OK { "id": 3, "name": "Повседневные траты", "balance": 0, "hold": 0, "type": "VISA", "status": "new", "user_id": 1 }
  27. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ИЗМЕНИТЬ БАЛАНС КОШЕЛЬКА 28 REQUEST: POST http://localhost:8080/api/v1/wallets/3/balance Content-Type: application/json { "balance": 300.0, "hold": 25.0 } RESPONSE: 200 OK { "id": 3, "name": "Повседневные траты", "balance": 300.0, "hold": 25.0, "type": "VISA", "status": "new", "user_id": 1 }
  28. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ИЗМЕНИТЬ СТАТУС КОШЕЛЬКА 29 REQUEST: POST http://localhost:8080/api/v1/wallets/3/approve RESPONSE: 200 OK { "id": 3, "name": "Повседневные траты", "balance": 300.0, "hold": 25.0, "type": "VISA", "status": "approved", "user_id": 1 }
  29. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 OPENAPI 30 Спецификация OpenAPI определяет стандарт независимого от языка описания API, который позволяет людям и машинам понимать возможности службы без доступа к исходному коду, документации или путем перехвата сетевого траффика. По сути, OpenAPI — это описание методов API, для которых описываются: query-параметры; заголовки и авторизация; схема входных и выходных сообщений; и т.п.
  30. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 31 1. openapi: 3.0.1 2. info: 3. title: OpenAPI definition 4. version: v0 5. servers: 6. - url: http://localhost:8080 7. paths: 8. /api/v1/persons: 9. get: 10. tags: 11. - person 12. - v1 13. summary: Get all Persons 14. responses: 15. "200": 16. description: All Persons 17. content: 18. application/json: 19. schema: 20. type: array 21. items: 22. $ref: '#/components/schemas/PersonResponse'
  31. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 CODE FIRST VS. CONTRACT FIRST 33 CODE FIRST – сначала пишется код контроллеров, а потом по этому коду генерируется описание. CONTRACT FIRST – сначала руками описывается и согласовывается со всеми заинтересованными сторонами контракт, а потом по этому контракту генерируется код.
  32. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ВЕРСИОНИРОВАНИЕ API 34 Версионирование в URL 
 /api/v1/public/users/... Версионирование в Headers 
 X-Api-Version: V1
  33. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 ВЫВОДЫ 35 RESTful – это все лишь набор рекомендаций, которые помогут построить выразительный и расширяемый API. Представления не обязательно должны соответствовать 1 к 1 доменным сущностям. Каждый ресурс на сервере имеет свой неизменяемый идентификатор, операции над сущностью выполняются в привязке этому идентификатору. API строится вокруг HTTP verbs, CRUD операции ложатся на них 1 к 1, иные операции выполняются через POST (или PUT) методы.
  34. © IT Enduro «Неудобные вопросы про RESTful или как проектировать

    API, чтобы не было так стыдно», 2024 БЛАГОДАРЮ ЗА ВНИМАНИЕ @romanow romanowalex @it_enduro it-endu.ro ПОДПИСКА И КОЛОКОЛЬЧИК 36