Неудобные вопросы про RESTful, или как проектировать API, чтобы не было так стыдно
Когда мы работаем с Микросервисной Архитектурой, часто возникает необходимость описать коммуникацию двух сервисов. Но как это сделать правильно, чтобы API выглядело понятно для потребителей, было простым в расширении и поддержке?
API, чтобы не было так стыдно», 2024 ПЛАН ДОКЛАДА Что такое RESTful API. Как применять RESTful: • что такое представление, как оно связано с доменной сущностью; • как CRUD ложится на HTTP verbs; • что такое stateless и почему это так важно в микросервисах. Пример: проектируем RESTful API для сущностей User, Address, Wallet. Описание API с помощью протокола OpenAPI. Плюсы и минусы подходов Contract first и Code first. Версионирование API. 2
опыт DevOps. Co-founder EdTech стартапа IT-Enduro. Работаю в роли Software Архитектора. Мы с вами встречались на других конференциях :) РОМАНОВ АЛЕКСЕЙ
API, чтобы не было так стыдно», 2024 ЧТО ТАКОЕ RESTFUL? 4 REST — это аббревиатура от Representational State Transfer (Передача Состояния Представления). Это согласованный набор архитектурных принципов для создания более масштабируемой и гибкой сети.
API, чтобы не было так стыдно», 2024 ЧТО ТАКОЕ RESTFUL? 5 Сервер содержит ресурсы и определяет операции над ними. Клиент работает с представлениями ресурсов, для изменения состояния сервера он передает желаемое представление ресурса на сервер. Это достигается за счет выполнения 4х ограничений. Определение ресурсов. Управление ресурсами через представления. Самодостаточные сообщения. Hypermedia as the Engine of Application State.
API, чтобы не было так стыдно», 2024 ЧТО ТАКОЕ ПРЕДСТАВЛЕНИЕ? 6 В терминологии RESTful ресурс – это информация, которую различные приложения предоставляют своим клиентам. Каждый ресурс должен иметь постоянный уникальный идентификатор. Управление ресурсами через представления – клиент управляет ресурсами, направляя серверу данные, обычно в виде JSON, содержащие представление, который он хотел бы добавить, удалить или изменить. Когда клиент хочет внести изменения в ресурсы, он посылает серверу представление того, каким он видит итоговый ресурс. Сервер принимает запрос как предложение, но за ним всё так же остаётся полный контроль.
API, чтобы не было так стыдно», 2024 CRUD МЕТОДЫ НА БАЗЕ HTTP 7 Методы HTTP (глаголы) составляют основную часть «единого интерфейса», ограничивающего и предоставляющего возможность осуществлять действия над существительным-ресурсом. НАЗВАНИЕ Описание POST Создание новых ресурсов. При успешном создании ресурса возвращается HTTP код 201, а также в заголовке «Location» передается адрес созданного ресурса. GET Получение представления ресурса. Запрос используется только для чтения данных, менять с помощью него состояние нельзя. PUT Полное обновление или создание ресурса. В отличие от POST, PUT метод передает ID ресурса, выбранного клиентом. PATCH Изменение представления существующего ресурса по ID. Возможна передача не полного представления, а только полей, которые требуется изменить. DELETE Используется для удаления ресурса, идентифицированного конкретным ID. C D R U
API, чтобы не было так стыдно», 2024 STATELESS 8 Отсутствие состояния (Stateless) подразумевает собой то, что необходимое состояние для обработки запроса содержится в самом запросе, либо в рамках URI, параметрах строки запроса, тела или заголовках. Определение URI уникально идентифицирует ресурс и тело, содержащее состояние этого ресурса. После того, как сервер завершит обработку, состояние или его часть отдается обратно клиенту через заголовки, статус и тело ответа. Клиент должен включать всю информацию для сервера для выполнения запроса.
API, чтобы не было так стыдно», 2024 РЕЗЮМИРУЯ 9 Фактически, RESTful – это всего лишь набор URI, HTTP вызовов к этим URI и некоторое количество представлений ресурсов в разных форматах. За основу адресации берется покрытие уникальными идентификаторами ресурсов: у каждого ресурса есть свой адрес, вся информация, которую сервер может предоставить, представлена как ресурс. Когда вы решаете, какие ресурсы буду в вашей системе, называйте их существительными, в противоположность глаголам, или действиям. Другими словами, URI должен ссылаться на ресурс, а не на действие.
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
API, чтобы не было так стыдно», 2024 ХОРОШИЙ, ПЛОХОЙ, ЗЛОЙ RESTFUL 11 Получение данных о заказах пользователя: НОРМАЛЬНО GET /users/{id}/orders ХОРОШО GET /orders/?userId=1 Сделать заказ от имени пользователя: НОРМАЛЬНО POST /users/{id}/orders body: {"items": [...]} ХОРОШО POST /orders body:{"userId": 1, "items": [...]}
API, чтобы не было так стыдно», 2024 ПОЛУЧИТЬ ВСЕХ ПОЛЬЗОВАТЕЛЕЙ 13 REQUEST: GET http://localhost:8080/api/v1/users RESPONSE: 200 OK [ { "id": 1, "firstName": "Алексей", "lastName": "Романов", "age": 33, "login": "romanow", "address": 1 } ]
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 }
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 } ]
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 }]
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": "Новогиреево" } }
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" }]
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
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 }
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 }
API, чтобы не было так стыдно», 2024 OPENAPI 30 Спецификация OpenAPI определяет стандарт независимого от языка описания API, который позволяет людям и машинам понимать возможности службы без доступа к исходному коду, документации или путем перехвата сетевого траффика. По сути, OpenAPI — это описание методов API, для которых описываются: query-параметры; заголовки и авторизация; схема входных и выходных сообщений; и т.п.
API, чтобы не было так стыдно», 2024 CODE FIRST VS. CONTRACT FIRST 33 CODE FIRST – сначала пишется код контроллеров, а потом по этому коду генерируется описание. CONTRACT FIRST – сначала руками описывается и согласовывается со всеми заинтересованными сторонами контракт, а потом по этому контракту генерируется код.
API, чтобы не было так стыдно», 2024 ВЫВОДЫ 35 RESTful – это все лишь набор рекомендаций, которые помогут построить выразительный и расширяемый API. Представления не обязательно должны соответствовать 1 к 1 доменным сущностям. Каждый ресурс на сервере имеет свой неизменяемый идентификатор, операции над сущностью выполняются в привязке этому идентификатору. API строится вокруг HTTP verbs, CRUD операции ложатся на них 1 к 1, иные операции выполняются через POST (или PUT) методы.