JavaRush /Java блог /Java Developer /Обзор REST. Часть 2: коммуникация между клиентом и сервер...

Обзор REST. Часть 2: коммуникация между клиентом и сервером

Статья из группы Java Developer
Часть 1: что такое REST В этой части мы подробно рассмотрим, каким образом происходит коммуникация между клиентом и сервером. Попутно мы будем раскрывать новые термины и давать к ним пояснения. Обзор REST. Часть 2: коммуникация между клиентом и сервером  - 1Чтобы все было (стало) понятно, будем разбирать клиент-серверную коммуникацию на примере некоторого RESTful приложения. Допустим, мы разрабатываем веб приложение, которое способно хранить информацию о клиентах и их заказах. Т.е. наша система способна манипулировать некоторыми сущностями: создавать их, редактировать, удалять, выдавать информацию о них. Этими сущностями будут:
  • clients — клиенты;
  • orders — заказы клиентов;
  • items — товары.
В REST архитектуре клиенты отправляют на сервер запросы для получения или модификации данных, а сервера отправляют клиентам ответы на их запросы.

Запросы

Клиентские запросы практически всегда сделаны по протоколу HTTP. В общем, HTTP запросы состоят из нескольких составляющих:
  • HTTP метод;
  • заголовок;
  • URI;
  • тело запроса.
Ниже мы рассмотрим более подробно каждую составляющую часть.

URI и Ресурсы

Данные, которые получают или изменяют клиенты посредством запросов, называют ресурсами. Основа клиент-серверного взаимодействия — манипуляция над ресурсами. Ресурсы в REST — это все, чему можно дать имя. Это в каком то смысле как классы в Java. В Java мы можем создать класс для чего угодно. Так и в REST — ресурсом может быть что угодно: пользователь, документ, отчет, заказ. Все это может быть как абстракцией некоторой сущности, так и чем-то конкретным, например, файлом — картинкой, видео, анимацией, PDF файлом. В рамках нашего примера у нас есть 3 ресурса:
  • clients — клиенты;
  • orders — заказы клиентов;
  • items — товары.
Клиенты отправляют запросы на так называемые эндпоинты, или же конечные точки (end point). Если говорить очень просто, эндпоинт — это что-то вроде адреса в сети. Если углубляться в суть, можно сказать, что эндпоинт — это URI: последовательность символов, идентифицирующая абстрактный или физический ресурс. Uniform Resource Identifier — унифицированный идентификатор ресурса. Иногда конечную точку, или URI называют путем (path) — путем до ресурса. В рамках этой статьи мы будем использовать термин URI. У каждого конкретного ресурса должен быть уникальный URI. Ответственность за то, чтобы у каждого ресурса всегда был свой URI лежит на плечах разработчика сервера. В нашем примере разработчики это мы, поэтому будем делать это так, как умеем. Подобно тому, как в реляционной базе данных часто принято первичным ключом задавать некоторый числовой ID, в REST у каждого ресурса есть свой ID. Часто бывает так, что ID ресурса в REST совпадает с ID записи в базе данных, в которой хранится информация о данном ресурсе. URI в REST принято начинать с множественной формы существительного, описывающего некоторый ресурс. Например, со слова clients. Далее через слэш указывают ID — идентификатор некоторого конкретного клиента. Примеры:
  • /clients — URI всех имеющихся клиентов;
  • /clients/23 — URI конкретного клиента, а именно клиента с ID=23;
  • /clients/4 — URI конкретного клиента, а именно клиента с ID=4.
Но и это еще не все. Мы можем продолжить URI, добавив к нему заказы:
  • /clients/4/orders — URI всех заказов клиента №4;
  • /clients/1/orders/12 — URI заказа №12 клиента №1.
Если мы продолжим эту цепочку и добавим еще и товары, получим:
  • /clients/1/orders/12/items — URI списка всех товаров в заказе №12 сделанного клиентом №1.
С уровнями вложенности главное — делать URI интуитивно понятными.

HTTP метод

Метод HTTP (англ. HTTP Method) — последовательность из любых символов, кроме управляющих и разделителей, которая указывает на основную операцию над ресурсом. Существует несколько общепринятых методов HTTP. Перечислим те из них, которые наиболее часто используются в RESTful сервисах:
  • GET — служит для получения информации о конкретном ресурсе (через ID) либо о коллекции ресурсов;
  • POST — служит для создания нового ресурса;
  • PUT — служит для изменения ресурса (через ID);
  • DELETE — служит для удаления ресурса (через ID).

Заголовки

В запросах, как собственно и в ответах, присутствуют HTTP заголовки. В них отправляется дополнительная информация о запросе (либо ответе). Заголовки представляют собой пары ключ-значение. Список наиболее распространенных заголовков можешь почитать на странице в Википедии. Применительно к REST клиенты часто могут слать в запросе к серверу заголовок Accept. Он нужен, чтобы дать серверу понять, в каком формате клиент ожидает получить от него ответ. Различные варианты форматов представлены в так называемом списке MIME-типов. MIME (англ. Multipurpose Internet Mail Extensions — многоцелевые расширения интернет-почты) — спецификация для кодирования информации и форматирования сообщений таким образом, чтобы их можно было пересылать по интернету. Каждый MIME тип состоит из двух частей, разделяемых слэшем — из типа и подтипа. Примеры MIME-типов для разных видов файлов:
  • text — text/plain, text/css, text/html;
  • image — image/png, image/jpeg, image/gif;
  • audio — audio/wav, audio/mpeg;
  • video — video/mp4, video/ogg;
  • application — application/json, application/pdf, application/xml, application/octet-stream.
Итого, у запроса может присутствовать заголовок:

Accept:application/json
Данный заголовок говорит серверу, что клиент ожидает получить ответ в JSON формате.

Тело запроса

Пересылаемое клиентом сообщение на сервер. Есть у запроса тело или нет, зависит от типа HTTP запроса. Например, запросы GET и DELETE как правило не содержат никакого тела запроса. А вот PUT и POST могут содержать: тут все дело в функциональном назначении типа запроса. Ведь для получения данных и удаления по id (который передается в URL) не нужно слать на сервер дополнительные данные. А вот для создания нового ресурса (запрос POST) нужно этот ресурс передать. Также как и для модификации существующего ресурса. В REST для передачи тела запроса чаще всего используют форматы XML или JSON. Наиболее часто встречается JSON формат. Предположим, мы хотим отправить на сервер запрос, а в нем — создать новый ресурс. Если ты не забыл, в качестве примера мы рассматривали приложение, которое управляет заказами клиентов. Допустим, мы хотим создать нового клиента. В нашем случае мы храним следующую информацию о клиентах: Имя Email Номер телефона Тогда телом такого запроса может быть следующий JSON:

{
  "name" : "Amigo",
  "email" : "amigo@jr.com",
  "phone" : "+7 (191) 746-43-23"
}

Собираем запросы воедино

Итак, мы рассмотрели с тобой из чего может состоять клиентский запрос. Приведем теперь несколько примеров запросов с описанием
Запрос Описание

GET /clients/23
Accept : application/json, application/xml
Получить информацию о клиенте №23 в формате json или xml

POST /clients
{
  "name" : "Amigo",
  "email" : "amigo@jr.com",
  "phone" : "+7 (191) 746-43-23"
}
Создать нового клиента с полями:
Имя — Amigo
Email — amigo@jr.com
Тел. — +7 (191) 746-43-23

PUT /clients/1
{
  "name" : "Ben",
  "email" : "bigben@jr.com",
  "phone" : "+380 (190) 346-42-13"
}
Редактировать клиента №1 в следующим образом:
Имя — Ben
Email — bigben@jr.com
Тел. — +380 (190) 346-42-13

DELETE /clients/12/orders/6
Удалить из системы заказ №6 у клиента №12

Ответы

Скажем пару слов об ответах сервера. Ответ как правило состоит из следующих частей:
  • код ответа;
  • заголовки;
  • тело ответа.
В целом заголовки ответов мало чем отличаются от заголовков запросов. К тому же, некоторые заголовки используются и в ответах, и в запросах. С телом ответа тоже, думаю, все понятно. В теле часто возвращается информация которую запросил клиент. Может возвращаться в том же формате JSON информация на GET запросы. А вот последняя часть, немного более интересна.

Коды HTTP ответов

Рассмотрим подробнее коды HTTP ответов. Приведем цитату из Википедии: Код состояния HTTP (англ. HTTP status code) — часть первой строки ответа сервера при запросах по протоколу HTTP. Он представляет собой целое число из трёх десятичных цифр. Первая цифра указывает на класс состояния. За кодом ответа обычно следует отделенная пробелом поясняющая фраза на английском языке, которая разъясняет человеку причину именно такого ответа. Примеры:
  • 201 Created;
  • 401 Unauthorized;
  • 507 Insufficient Storage.
Клиент узнаёт по коду ответа о результатах его запроса и определяет, какие действия ему предпринимать дальше. Коды ответов подразделяются на несколько групп:
  • 1ХХ — информационные;
  • 2ХХ — информируют о случаях успешного принятия и обработки запроса клиента;
  • 3ХХ — сообщают клиенту, что для успешного выполнения операции необходимо сделать другой запрос, как правило по другому URI;
  • 4ХХ — ошибка клиента. Например, неправильно составленный запрос или же широко известный код 404 Not Found, которая может возникнуть, когда клиент запрашивает несуществующий ресурс;
  • 5ХХ — ошибка сервера. Возвращается клиенту в случае неудачного выполнения операции по вине сервера.
Более подробно обо всех кодах можно почитать тут. Часть 1: что такое REST Часть 3: создание RESTful сервиса на Spring Boot
Комментарии (8)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Максим Li Уровень 36
20 ноября 2023
Полезная статья, спасибо)
wan-derer.ru Уровень 40
24 февраля 2023
Дополню. HTTP-метод UPDATE используется для изменения существующего ресурса. Но, в отличие от PUT, передаётся не объект целиком, а какая-то его часть. Например, UPDATE надо использовать если у клиента Amigo надо поменять только поле email.
Fidel Уровень 1
23 января 2020
Добавлю свои 5 копеек, исходя из вопросов на собеседованиях, касательно REST-а. 1. Что такое идемпотентные (idempotent) запросы? Это запросы, повторение которых не изменяет состояние ресурсов сервера. GET, HEAD, PUT, DELETE являются идемпотентными. POST к таким не относится, так как каждый следующий запрос будет создавать новый ресурс. В то же время два последовательных одинаковых запроса DELETE вернут разные коды 200 и 404, но он при этом остается идемпотентным. 2. Для чего существует метод HEAD? HEAD запрос должен возвращать тот же результат что и GET исключая тело ответа (обычно это метаинформация о ресурсе). Его обычно вызывают перед загрузкою обьемного ресурса для проверки его размера, видимости, доступа и недавних изменений. Также можно почитать про метод OPTIONS.
Maksim Уровень 40
21 января 2020
Информативно. Спасибо. Вот опечатка: "/clients/4 — URI конкретного клиента, а именно клиента с ID=23."
Vitaly Khan Уровень 40 Master
20 января 2020
все здорово, но ошибки неплохо бы исправить: "audio — audio/wav, image/mpeg;" "А вот последняя часть, немного более интересна." (на самом деле - первая) перед публикацией статьи лучше дать ее прочитать внимательному человеку (не автору статьи).