REST, Representational State Transfer, является архитектурным стилем для обеспечения стандартов между компьютерными системами в сети, что облегчает для систем обмен данными друг с другом. Системы, отвечающие требованиям REST и часто называемые RESTful, характеризуются тем, что не имеют сохранения состояния и разделяют интересы клиента и сервера. Мы рассмотрим, что означают эти термины и почему они являются полезными для услуг в Интернете.
До тех пор, пока каждая сторона знает, какой формат сообщений следует направлять другой стороне, они могут храниться модульно и раздельно. Отделяя задачи пользовательского интерфейса от задач хранения данных, мы повышаем гибкость интерфейса между платформами и улучшаем расширяемость за счёт упрощения компонентов сервера. Кроме того, разделение позволяет каждому компоненту развиваться независимо.
Используя интерфейс REST, различные клиенты попадают в одни и те же конечные точки REST, выполняют те же действия и получают одинаковые ответы.
Эти ограничения помогают RESTful-приложениям достигать надёжности, быстрой производительности и расширяемости, как компонентам, которые могут быть управляемы, обновлены и повторно использованы, не затрагивая систему в целом даже во время её работы.
Теперь мы изучим, как на самом деле происходит взаимодействие между клиентом и сервером, когда мы внедряем RESTful-интерфейс.
Типы MIME, используемые для указания типов контента в поле Accept, состоят из типа и подтипа. Они разделены слэшем (/).
Например, текстовый файл, содержащий HTML, будет указан с типом text/html. Если этот текстовый файл содержит CSS, то он будет указан как text/css. Общий текстовый файл будет обозначаться как text/plain. Однако это значение по умолчанию, text/plain, не является исчерпывающим. Если клиент ожидает text/css, а получает text/plain, он не сможет распознать содержание.
Другие типы и часто используемые подтипы:
GET/news/123
Accept: text/html, application/xhtml
В этом случае поле заголовка Accept говорит, что клиент примет содержание в text/html или application/xhtml.
Запросы должны содержать путь к ресурсу, на котором должна выполняться операция. В RESTful API пути должны быть разработаны так, чтобы помочь клиенту понять, что происходит. Обычно первая часть пути должна быть множественной формой ресурса. Это позволяет легко читать и понимать вложенные пути.
Пути должны содержать информацию, необходимую для определения местоположения ресурса с необходимой степенью конкретности. При ссылке на список или коллекцию ресурсов не всегда необходимо добавлять идентификатор. Например, запрос POST на путь somesite.com/persons не будет нуждаться в дополнительном идентификаторе, так как сервер генерирует идентификатор для нового объекта.
В тех случаях, когда сервер отправляет клиенту полезную нагрузку, он должен включать тип контента в заголовок ответа. Это поле заголовка контента предупреждает клиента о типе данных, которые он посылает в теле ответа. Эти типы контента являются типами MIME, точно так же, как они находятся в поле Accept заголовка запроса. Тип контента, который сервер возвращает обратно в ответе, должен быть одним из параметров, указанных клиентом в поле принятия запроса.
Например, клиент получает доступ к ресурсу с идентификатором 123 в разделе статей с этим запросом GET:
GET /news/123 HTTP/1.1
Accept: text/html, application/xhtml
Сервер должен отправить обратно контент с заголовком ответа:
HTTP/1.1 200 (OK)
Content-Type: text/html
Это означает, что запрашиваемый контент возвращается в тело ответа с text/html — типом контента, который клиент будет в состоянии принять.
Для каждого метода НТТР ожидаются коды статуса, которые сервер должен вернуть в случае успеха:
Предположим, у нас есть приложение, которое позволяет вам просматривать, создавать, редактировать и удалять клиентов и заказы для небольшого магазина одежды, размещённого на сайте fashionboutique.com. Мы можем создать НТТР API, который позволит клиенту выполнять следующие функции.
Если бы мы хотели увидеть всех клиентов, запрос выглядел бы так:
GET http://somesite.com/persons
Accept: application/json
Возможный заголовок ответа будет выглядеть следующим образом:
Status Code: 200 (OK)
Content-type: application/json
Затем следуют данные клиентов, запрошенные в формате application/json.
Создание нового клиента путем размещения данных:
POST http://somesite.com/persons
Body:
{
“person”: {
“name” = “oleg Melnic”,
“email” = “oleg.melnic@gmail.com”
}
}
Затем сервер генерирует идентификатор этого объекта и возвращает его клиенту с таким заголовком:
201 (CREATED)
Content-type: application/json
Для просмотра одного клиента мы используем метод GET, указывая идентификатор этого клиента:
GET http://somesite.com/persons/123
Accept: application/json
Возможный заголовок ответа будет выглядеть следующим образом:
Status Code: 200 (OK)
Content-type: application/json
Затем следуют данные ресурса клиента с идентификатором 123 в формате application/json.
Мы можем обновить этого клиента, вставив новые данные с помощью метода PUT:
PUT http://somesite.com/persons/123
Body:
{
“person”: {
“name” = “Oleg Melnic”,
“email” = “olegmelnic1@gmail.com”
}
}
Возможный заголовок ответа будет иметь Status Code: 200 (OK), чтобы сообщить клиенту, что элемент с идентификатором 123 был изменен.
Мы также можем УДАЛИТЬ этого клиента, указав его идентификатор:
DELETE http://somesite.com/persons/123
Ответ будет иметь заголовок, содержащий Status Code: 204 (NO CONTENT), уведомляющий клиента о том, что объект с идентификатором 123 был удалён и ничего в теле не осталось.
“user”: {
"id": <Integer>,
“username”: <String>,
“password”: <String>
}
}
{
“photo”: {
"id": <Integer>,
“address_id”: <Integer>,
“user_id”: <Integer>
}
}
{
“address”: {
"id": <Integer>,
“name”: <String>,
“value”: <String>
}
}
GET /index.html
Accept: text/html
Response
200 (OK)
Content-type: text/html
Request
GET /style.css
Accept: text/css
Response
200 (OK)
Content-type: text/css
Request
GET /addresses
Accept: application/json
Response
200 (OK)
Content-type: application/json
Request
GET /addresses/:id
Accept: application/json
Response
200 (OK)
Content-type: application/json
Request
GET /addresses/:id /photos/:id
Accept: application/json
Response
200 (OK)
Content-type: image/png
POST /users
Response
201 (CREATED)
Content-type: application/json
Request
POST /addresses
Response
201 (CREATED)
Content-type: application/json
Request
POST /addresses/:id /photos
Response
201 (CREATED)
Content-type: application/json
PUT /users/:id
Response
200 (OK)
Request
PUT /addresses/:id
Response
200 (OK)
Request
PUT /addresses/:id /photos/:id
Response
200 (OK)
DELETE /addresses/:id
Response
204 (NO CONTENT)
Request
DELETE /addresses/:id/ photos/:id
Response
204 (NO CONTENT)
Посмотрите также статью про лучшие практики разработки REST API. 20 советов помогут вам создавать понятные API.
Источник статьи: https://tproger.ru/articles/osnovy-rest-teorija-i-praktika/
Разделение клиента и сервера
В архитектурном стиле REST реализация клиента и реализация сервера могут быть выполнены независимо друг от друга. Это означает, что код на стороне клиента может быть изменён в любое время без ущерба для работы сервера, а код на стороне сервера может быть изменён без влияния на работу клиента.До тех пор, пока каждая сторона знает, какой формат сообщений следует направлять другой стороне, они могут храниться модульно и раздельно. Отделяя задачи пользовательского интерфейса от задач хранения данных, мы повышаем гибкость интерфейса между платформами и улучшаем расширяемость за счёт упрощения компонентов сервера. Кроме того, разделение позволяет каждому компоненту развиваться независимо.
Используя интерфейс REST, различные клиенты попадают в одни и те же конечные точки REST, выполняют те же действия и получают одинаковые ответы.
Отсутствие сохранения состояния
Системы, которые следуют парадигме REST, не имеют сохранения состояния, что означает, что серверу не нужно знать о состоянии клиента и наоборот. Таким образом, и сервер, и клиент могут понять любое полученное сообщение, даже не увидев предыдущих сообщений. Это отсутствие сохранения состояния обеспечивается за счёт использования ресурсов, а не команд. Они описывают любые объекты, документы или вещи, которые могут потребоваться для хранения или отправки в другие службы.Эти ограничения помогают RESTful-приложениям достигать надёжности, быстрой производительности и расширяемости, как компонентам, которые могут быть управляемы, обновлены и повторно использованы, не затрагивая систему в целом даже во время её работы.
Теперь мы изучим, как на самом деле происходит взаимодействие между клиентом и сервером, когда мы внедряем RESTful-интерфейс.
Взаимодействие между клиентом и сервером
В архитектуре REST клиенты отправляют запросы на поиск или изменение ресурсов, а серверы отправляют ответы на эти запросы. Давайте рассмотрим стандартные способы направления запросов и ответов.Отправка запросов
REST требует, чтобы клиент сделал запрос на сервер для получения или изменения данных на сервере. Запрос обычно состоит из:- НТТР-метода, который определяет вид операции;
- заголовка, который позволяет клиенту передавать информацию о запросе;
- пути к ресурсу;
- необязательного тела сообщения, содержащего данные.
- GET — получение конкретного ресурса (по id) или коллекцию ресурсов;
- POST — создание нового ресурса;
- PUT — обновление конкретного ресурса (по id);
- DELETE — удаление конкретного ресурса по id;
Типы MIME, используемые для указания типов контента в поле Accept, состоят из типа и подтипа. Они разделены слэшем (/).
Например, текстовый файл, содержащий HTML, будет указан с типом text/html. Если этот текстовый файл содержит CSS, то он будет указан как text/css. Общий текстовый файл будет обозначаться как text/plain. Однако это значение по умолчанию, text/plain, не является исчерпывающим. Если клиент ожидает text/css, а получает text/plain, он не сможет распознать содержание.
Другие типы и часто используемые подтипы:
- 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.
GET/news/123
Accept: text/html, application/xhtml
В этом случае поле заголовка Accept говорит, что клиент примет содержание в text/html или application/xhtml.
Запросы должны содержать путь к ресурсу, на котором должна выполняться операция. В RESTful API пути должны быть разработаны так, чтобы помочь клиенту понять, что происходит. Обычно первая часть пути должна быть множественной формой ресурса. Это позволяет легко читать и понимать вложенные пути.
Пути должны содержать информацию, необходимую для определения местоположения ресурса с необходимой степенью конкретности. При ссылке на список или коллекцию ресурсов не всегда необходимо добавлять идентификатор. Например, запрос POST на путь somesite.com/persons не будет нуждаться в дополнительном идентификаторе, так как сервер генерирует идентификатор для нового объекта.
В тех случаях, когда сервер отправляет клиенту полезную нагрузку, он должен включать тип контента в заголовок ответа. Это поле заголовка контента предупреждает клиента о типе данных, которые он посылает в теле ответа. Эти типы контента являются типами MIME, точно так же, как они находятся в поле Accept заголовка запроса. Тип контента, который сервер возвращает обратно в ответе, должен быть одним из параметров, указанных клиентом в поле принятия запроса.
Например, клиент получает доступ к ресурсу с идентификатором 123 в разделе статей с этим запросом GET:
GET /news/123 HTTP/1.1
Accept: text/html, application/xhtml
Сервер должен отправить обратно контент с заголовком ответа:
HTTP/1.1 200 (OK)
Content-Type: text/html
Это означает, что запрашиваемый контент возвращается в тело ответа с text/html — типом контента, который клиент будет в состоянии принять.
Коды ответов
Ответы от сервера содержат коды состояния для оповещения клиента об успехе операции. Как разработчику вам не нужно знать каждый код состояния (их много), но вы должны знать самые распространённые и то, как они используются.Для каждого метода НТТР ожидаются коды статуса, которые сервер должен вернуть в случае успеха:
- GET — return 200 (OK)
- POST — return 201 (CREATED)
- PUT — return 200 (OK)
- DELETE — return 204 (NO CONTENT)
Предположим, у нас есть приложение, которое позволяет вам просматривать, создавать, редактировать и удалять клиентов и заказы для небольшого магазина одежды, размещённого на сайте fashionboutique.com. Мы можем создать НТТР API, который позволит клиенту выполнять следующие функции.
Если бы мы хотели увидеть всех клиентов, запрос выглядел бы так:
GET http://somesite.com/persons
Accept: application/json
Возможный заголовок ответа будет выглядеть следующим образом:
Status Code: 200 (OK)
Content-type: application/json
Затем следуют данные клиентов, запрошенные в формате application/json.
Создание нового клиента путем размещения данных:
POST http://somesite.com/persons
Body:
{
“person”: {
“name” = “oleg Melnic”,
“email” = “oleg.melnic@gmail.com”
}
}
Затем сервер генерирует идентификатор этого объекта и возвращает его клиенту с таким заголовком:
201 (CREATED)
Content-type: application/json
Для просмотра одного клиента мы используем метод GET, указывая идентификатор этого клиента:
GET http://somesite.com/persons/123
Accept: application/json
Возможный заголовок ответа будет выглядеть следующим образом:
Status Code: 200 (OK)
Content-type: application/json
Затем следуют данные ресурса клиента с идентификатором 123 в формате application/json.
Мы можем обновить этого клиента, вставив новые данные с помощью метода PUT:
PUT http://somesite.com/persons/123
Body:
{
“person”: {
“name” = “Oleg Melnic”,
“email” = “olegmelnic1@gmail.com”
}
}
Возможный заголовок ответа будет иметь Status Code: 200 (OK), чтобы сообщить клиенту, что элемент с идентификатором 123 был изменен.
Мы также можем УДАЛИТЬ этого клиента, указав его идентификатор:
DELETE http://somesite.com/persons/123
Ответ будет иметь заголовок, содержащий Status Code: 204 (NO CONTENT), уведомляющий клиента о том, что объект с идентификатором 123 был удалён и ничего в теле не осталось.
Практика с REST
Давайте представим, что мы создаём сайт для сбора фотографий. Мы хотим сделать API, чтобы отслеживать пользователей, места проведения и фотографии этих мест. Этот сайт имеет index.html и style.css. Каждый пользователь имеет имя пользователя и пароль. Каждая фотография имеет место проведения и владельца (т.е. пользователя, который сделал фотографию). Каждое место имеет название и адрес. Можете ли вы разработать систему REST, которая будет учитывать:- хранение пользователей, фотографий и мест проведения;
- доступ к определённым местам и доступ к некоторым фотографиям определённого места проведения?
- какие запросы мы хотели бы сделать;
- какие ответы должен вернуть сервер;
- каким должно быть содержание каждого ответа.
Возможные решения — модели
{“user”: {
"id": <Integer>,
“username”: <String>,
“password”: <String>
}
}
{
“photo”: {
"id": <Integer>,
“address_id”: <Integer>,
“user_id”: <Integer>
}
}
{
“address”: {
"id": <Integer>,
“name”: <String>,
“value”: <String>
}
}
Возможное решение — запросы / ответы
GET-запросы
RequestGET /index.html
Accept: text/html
Response
200 (OK)
Content-type: text/html
Request
GET /style.css
Accept: text/css
Response
200 (OK)
Content-type: text/css
Request
GET /addresses
Accept: application/json
Response
200 (OK)
Content-type: application/json
Request
GET /addresses/:id
Accept: application/json
Response
200 (OK)
Content-type: application/json
Request
GET /addresses/:id /photos/:id
Accept: application/json
Response
200 (OK)
Content-type: image/png
POST-запросы
RequestPOST /users
Response
201 (CREATED)
Content-type: application/json
Request
POST /addresses
Response
201 (CREATED)
Content-type: application/json
Request
POST /addresses/:id /photos
Response
201 (CREATED)
Content-type: application/json
PUT-запросы
RequestPUT /users/:id
Response
200 (OK)
Request
PUT /addresses/:id
Response
200 (OK)
Request
PUT /addresses/:id /photos/:id
Response
200 (OK)
DELETE-запросы
RequestDELETE /addresses/:id
Response
204 (NO CONTENT)
Request
DELETE /addresses/:id/ photos/:id
Response
204 (NO CONTENT)
Посмотрите также статью про лучшие практики разработки REST API. 20 советов помогут вам создавать понятные API.
Источник статьи: https://tproger.ru/articles/osnovy-rest-teorija-i-praktika/