REST - основной архитектурный принцип сети. Удивительным моментом в Интернете является тот факт, что клиенты (браузеры) и серверы могут взаимодействовать сложным образом, и клиент ничего не знает заранее о сервере и размещенных на нем ресурсах. Ключевым ограничением является то, что сервер и клиент должны согласовать используемое media , которое в случае с Интернетом равно HTML .
API, который придерживается принципов REST , не требует от клиента ничего знать о структуре API. Скорее, сервер должен предоставить любую информацию, необходимую клиенту для взаимодействия со службой. HTML-форма является примером этого: сервер указывает местоположение ресурса и обязательные поля. Браузер заранее не знает, куда отправлять информацию, и заранее не знает, какую информацию отправлять. Обе формы информации полностью предоставляются сервером. (Этот принцип называется HATEOAS : гипермедиа как двигатель состояния приложения .)
Итак, как это относится к HTTP и как его можно реализовать на практике? HTTP ориентируется на глаголы и ресурсы. В основном употреблении используются два глагола: GET
и POST
, которые, я думаю, все узнают. Тем не менее, стандарт HTTP определяет несколько других, таких как PUT
и DELETE
. Затем эти глаголы применяются к ресурсам в соответствии с инструкциями, предоставленными сервером.
Например, давайте представим, что у нас есть пользовательская база данных, которая управляется веб-службой. Наш сервис использует пользовательские гипермедиа на основе JSON, для которых мы назначаем mimetype application/json+userdb
(также могут быть application/xml+userdb
и application/whatever+userdb
- могут поддерживаться многие типы медиа). Клиент и сервер были запрограммированы для понимания этого формата, но они ничего не знают друг о друге. Как Рой Филдинг указывает:
API REST должен тратить почти все свои описательные усилия на
определение типа (ов) медиа, используемых для представления ресурсов и управления ими
состояние приложения или при определении расширенных имен отношений и / или
разметка с поддержкой гипертекста для существующих стандартных типов носителей.
Запрос на базовый ресурс /
может вернуть что-то вроде этого:
Запрос
GET /
Accept: application/json+userdb
Ответ
200 OK
Content-Type: application/json+userdb
{
"version": "1.0",
"links": [
{
"href": "/user",
"rel": "list",
"method": "GET"
},
{
"href": "/user",
"rel": "create",
"method": "POST"
}
]
}
Мы знаем из описания наших СМИ, что мы можем найти информацию о связанных ресурсах в разделах, называемых «ссылками». Это называется Гипермедиа управления . В этом случае мы можем сказать из такого раздела, что мы можем найти список пользователей, сделав еще один запрос для /user
:
Запрос
GET /user
Accept: application/json+userdb
Ответ
200 OK
Content-Type: application/json+userdb
{
"users": [
{
"id": 1,
"name": "Emil",
"country: "Sweden",
"links": [
{
"href": "/user/1",
"rel": "self",
"method": "GET"
},
{
"href": "/user/1",
"rel": "edit",
"method": "PUT"
},
{
"href": "/user/1",
"rel": "delete",
"method": "DELETE"
}
]
},
{
"id": 2,
"name": "Adam",
"country: "Scotland",
"links": [
{
"href": "/user/2",
"rel": "self",
"method": "GET"
},
{
"href": "/user/2",
"rel": "edit",
"method": "PUT"
},
{
"href": "/user/2",
"rel": "delete",
"method": "DELETE"
}
]
}
],
"links": [
{
"href": "/user",
"rel": "create",
"method": "POST"
}
]
}
Мы можем многое сказать по этому ответу. Например, теперь мы знаем, что можем создать нового пользователя путем POST
в /user
:
Запрос
POST /user
Accept: application/json+userdb
Content-Type: application/json+userdb
{
"name": "Karl",
"country": "Austria"
}
Ответ
201 Created
Content-Type: application/json+userdb
{
"user": {
"id": 3,
"name": "Karl",
"country": "Austria",
"links": [
{
"href": "/user/3",
"rel": "self",
"method": "GET"
},
{
"href": "/user/3",
"rel": "edit",
"method": "PUT"
},
{
"href": "/user/3",
"rel": "delete",
"method": "DELETE"
}
]
},
"links": {
"href": "/user",
"rel": "list",
"method": "GET"
}
}
Мы также знаем, что можем изменить существующие данные:
Запрос
PUT /user/1
Accept: application/json+userdb
Content-Type: application/json+userdb
{
"name": "Emil",
"country": "Bhutan"
}
Ответ
200 OK
Content-Type: application/json+userdb
{
"user": {
"id": 1,
"name": "Emil",
"country": "Bhutan",
"links": [
{
"href": "/user/1",
"rel": "self",
"method": "GET"
},
{
"href": "/user/1",
"rel": "edit",
"method": "PUT"
},
{
"href": "/user/1",
"rel": "delete",
"method": "DELETE"
}
]
},
"links": {
"href": "/user",
"rel": "list",
"method": "GET"
}
}
Обратите внимание, что мы используем различные глаголы HTTP (GET
, PUT
, POST
, DELETE
и т. Д.) Для манипулирования этими ресурсами, и что единственное знание, которое мы предполагаем со стороны клиента, - это наше определение медиа .
Дополнительное чтение:
(Этот ответ был предметом значительной критики за то, что он упустил суть. По большей части это была справедливая критика. То, что я первоначально описал, больше соответствовало тому, как REST обычно применялся в течение нескольких лет. назад, когда я впервые написал это, а не его истинное значение. Я изменил ответ, чтобы лучше представить реальное значение.)