REST
- representational state transfer (en)
- передача состояния представления (ru)
- архитектура для построения веб-приложений
- Рой Филдинг, диссертация, 2000
- использует семантику запросов-ответов
- позволяет достичь производительности, надежности, масштабируемости
- RESTful-системы
REST - Основы
- клиент-серверная архитектура
- отсутствие состояния
- кэширование
- унифицированный интерфейс
- слои сервисов
- доставка кода (необязательно)
- идентификация ресурсов через URL
- запрос самоописывает себя
- изменение состояния через запросы
REST - Сильные стороны
- производительность (кэширование)
- надёжность (отсутствие состояния)
- масштабируемость (отсутствие состояния, простота и предсказуемость интерфеса, лёгкое изменение)
REST - Методы
- GET - чтение ресурса или коллекции
- PUT - обновление существующего ресурса или коллекции
- DELETE - удаление существующего ресурса
- POST - создание ресурса + все остальные действия
REST - Именование
- идентификаторы вместо query
- +: /users/12345
- -: /api?type=user&id=23
- -: /users?id=23
REST - Именование
- используйте иерархию
- GET /users/12345/comments
- но не стоит делать слишком большую вложенность
- 2-3 оптимально
REST - Именование
- используйте существительные
- избегайте глаголов
- +: POST /users
- -: POST /users/update
REST - Именование
- используйте множественное число для консистентности
- +: GET /customers/33245/orders/8769
- -: GET /customer/33245/order/8769
REST - Именование
- используйте kebab-case
- +: GET /customers/33245/delivery-addresses
- -: GET /customers/33245/deliveryAddresses
REST - Именование
- не указывайте тип коллекции
- +: GET /customers
- -: GET /customer-list
REST - Статус
- используйте HTTP статусы для ответа
- 200, 201, 204, 400, 401, 403, 404, 405, 409, 500
REST - Форматы
- рекомендуется поддерживать json и xml
REST - Версионирование
- версия API как часть URL
- версия API - целое число
- GET /api/v1/users
REST - Версионирование
- или версионирование схем данных
- http://api.schemas.wrml.org/soccer/Player
- http://api.schemas.wrml.org/soccer/Player-2
REST - Ответ
// +
"tags": [
{"id": "125", "name": "Environment"},
{"id": "834", "name": "Water Quality"}
]
// -
"tags": [
{"125": "Environment"},
{"834": "Water Quality"}
]
REST - Пагинация
- limit по-умолчанию
- информация о пагинации включена в ответ
- GET /api/v1/users?limit=25&offset=50
{
"metadata": {
"count": 308,
"offset": 50,
"limit": 25
},
"users": [ ... ]
}
REST - Сортировка, фильтрация
GET /users?sort=last_name|first_name|-hire_date
GET /users?filter=name::todd|city::denver
REST - Ошибки
{
"message": "The Error",
"code": "server-error",
"status": 500,
// optional
"developerMessage": "Hi developer!",
"moreInfo": "http://example.com/server-error"
}
REST - Заголовки
- Content-Type, Accept
- Cache-Control, Expires, ETag для GET
- Location для POST
- If-Unmodified-Since для PUT
REST - HATEOAS
// Hypertext As The Engine Of Application State
// GET /api/v1/
{
"links": {
"users": "/api/v1/users"
"posts": "/api/v1/posts/"
}
}
REST - HATEOAS
// Hypertext As The Engine Of Application State
// GET /api/v1/posts
{
"links": {
"post": "/api/v1/posts/:id"
}
}
REST - HATEOAS
// Hypertext As The Engine Of Application State
// GET /api/v1/posts/42
{
"links": {
"comments": "/api/v1/posts/42/comments"
}
}
REST - Примеры
- /api/sessions - GET, POST, DELETE
- /api/users/{login}/password - PUT
- /api/users/{login}/tokens - DELETE
- /api/alerts/{id}/activation - GET/POST
- /api/alerts/{id}/cancellation - GET/POST
REST - Примеры
- GET /media/{media-id}
- GET /media/search?lat=48.858844&lng=2.294351
- GET /media/{media-id}/likes
- POST /media/{media-id}/likes
- DELETE /media/{media-id}/likes
REST + Express
// controllers/base.js
...
this.routes = {
'/': [
{ method: 'get', cb: readAll },
{ method: 'post', cb: create }
],
'/:id': [
{ method: 'get', cb: read },
{ method: 'put', cb: update },
{ method: 'delete', cb: del }
]
};
...
REST + Express
// controllers/base.js
...
function update(req, res) {
req.body.id = req.params.id;
...
}
...
REST - Литература
- RESTful Service Best Practices / Todd Fredrich
- REST API Design Rulebook / Mark Masse