Как спроектировать rest api

Приветствую друзья! В этой статье будет краткий мануал по проектированию интерфейса rest api, рассмотрим частые ошибки и используемые стандарты.
Поехали!
Версия api
Чтобы в дальнейшем не было проблем с поддержкой, рекомендуется разделять api по версиям. Сделать это можно добавив название мажорной версии в url
/api/v1/users/1
/api/v2/users/1
...
Лучше использовать версионирование api, чем не использовать
Правила именования роутов
Не используем слэш в конце url
Ко многим разделам вашего api могут идти дополнительные атрибуты, и не всегда интуитивно понятно что их можно добавить если на конце стоит закрывающий слэш
/api/v1/posts
/api/v1/posts/ // не верно
/api/v1/posts/categories
/api/v1/posts/categories/ // не верно
/api/v1/posts?offset=12
/api/v1/posts/?offset=12 // не верно
Именование во множественном числе
Старайтесь всегда называть разделы api во множественном числе, так как существуют слова употребляемые только во множественном числе (glasses, money, clothes), и чтобы в дальнейшем не было путаницы, лучше давать имена в одном стиле
/api/v1/posts
/api/v1/post // не верно
/api/v1/post/categories // не верно
/api/v1/posts/category // не верно
/api/v1/posts/categories
Выборка по id
Чтобы получить например, данные заказа, в api должно быть достаточно передать его id
/api/orders/(( id ))
/api/orders/1
Логическая цепочка
Для того чтобы api было интуитивно понятным, необходимо соблюдать логическую цепочку наименования разделов. К примеру нам нужно получить категории поста, логично сделать так 'Все посты -> конкретный пост -> категории'
/api/v1/posts/1/categories
/api/v1/categories/1 // не верно
/api/v1/categories?post=1 // не верно
Параметры запросов
Как правило параметры задаются в формате get в конце url. К примеру нам нужно получить только пять записей
/api/v1/posts?limit=5
/api/v1/posts/limit/5 // не верно
CRUD - create read update delete
С построением get(получить) запросов мы разобрались, теперь возмемся за создание, изменение, удаление данных. Здесь одним url не обойтись, нам нужны типы запросов POST, PUT, DELETE
Создание - post
Создание записей как правило производится POST запросом на необходимый раздел api, никаких /create/ /build/ /add/ в роуте прописывать не нужно, здесь идет фильтрация типа запроса
К примеру чтобы создать пост, нам нужно отправить POST запрос на подобный url
/api/v1/posts
/api/v1/posts/create // не верно
Чтение - GET
Стандартный get запрос на получение данных
Изменение - PUT
Как и в случае с созданием, url нам править не нужно, нужно только отфильтровать запрос по типу. Для изменения данных используется тип запроса PUT. Вот пример url для изменения поста запросом PUT
/api/v1/posts/1
Удаление - DELETE
Аналогично предыдущим, удаление производится только изменением типа запроса на DELETE
Все действия производятся только с помощью изменения запроса. Никогда не используйте глаголы в url
Ответ сервера
Сервер всегда должен возвращать http коды, вот стандартный список ответов сервера которые обязательно нужно реализовать
- 200: Done, it was okay. // Обычно GET возвращает этот код.
- 201: “Done, and created.” // Обычно POST возвращает этот код.
- 204: “Done, and no body.” // Обычно DELETE возвращает этот код.
- 400: “Client sent me junk, and I’m not going to mess with it.”
- 401: “Unauthorized, the client should authenticate first.”
- 403: “Not allowed. You can’t have it because you logged in but don’t have permission to this thing or to delete this thing.”
- 404: “Can’t find it.”
- 410: “Marked as deleted.”
- 451: “The government made me not show it.”
Пример хорошего api блога
+--------+----------------------------------------+------------------------------------------------------+ | | POST | login | | | POST | logout | | | POST | password-recovery | | | | | | | GET | posts?offset={n}&limit={n} | | | POST | posts | | | PUT | posts | | | DELETE | posts | | | GET | posts/{n}/ | | | GET | posts/{n}/categories | | | | | | | GET | categories?offset={n}&limit={n} | | | POST | categories | | | PUT | categories | | | DELETE | categories | +--------+----------------------------------------+------------------------------------------------------+