Шпаргалка по созданию RESTful API

RESTful API может создаваться не только для сторонних сервисов. Он может использоваться одностраничными приложениями для работы с бэк-эндом. Вот несколько основных моментов, которые нужно знать при проектировании интерфейса.

URLs и действия

Ключевым принципом REST является деление вашего API на логические ресурсы. Управление этими ресурсами происходит с помощью HTTP-запросов с соответствующим методом — GET, POST, PUT, PATCH, DELETE.

Ресурс должен описываться существительным во множественном числе. Действия над ресурсами, обычно, определяются стратегией CRUD и соответствуют HTTP-методам следующим образом:

  • GET /api/users — получить список пользователей;
  • GET /api/users/123 — получить указанного пользователя;
  • POST /api/users — создать нового пользователя;
  • PUT /api/users/123 — обновить все данные указанного пользователя;
  • PATCH /api/users/123 — частично обновить данные пользователя;
  • DELETE /api/users/123 — удалить пользователя.

Если ресурс существует только в контексте другого ресурса, то URL может быть составным:

  • GET /api/posts/9/comments — получить список комментариев к записи №9;
  • GET /api/posts/9/comments/3 — получить комментарий №3 к записи №9.

Когда действие над объектом не соответствует CRUD операции, то его можно рассматривать как составной ресурс:

  • POST /api/posts/9/like — отметить запись №9 как понравившуюся;
  • DELETE /api/posts/9/like — снять отметку «понравилось» с записи №9.

Действия по созданию и обновлению ресурсов должны возвращать ресурс

Методы POST, PUT или PATCH могут изменять поля ресурса, которые не были включены в запрос (например, ID, дата создания или дата обновления). Чтобы не вынуждать пользователя API выполнять ещё один запрос на получение обновлённых данных, такие методы должны вернуть их в ответе.

Фильтры, сортировка и поиск

Любые параметры в HTTP-запросе могут быть использованы для уточнения запроса или сортировки данных.

  • GET /api/users?state=active — список активных пользователей;
  • GET /api/tasks?state=open&sort=priority,-created_at — список невыполненных задач, отсортированных по приоритету и дате создания (сперва новые задачи).

Постраничная навигация

Когда нужно в ответ на запрос списка объектов добавить информацию о постраничной навигации, стоит воспользоваться HTTP-заголовком Link, а не добавлять обёртки данным.

Пример заголовка:

Link: <http://domain.tld/api/users?page=5&per_page=100>; rel="next",
    <http://domain.tld/api/users?page=3&per_page=100>; rel="prev",
    <http://domain.tld/api/users?page=1&per_page=100>; rel="first",
    <http://domain.tld/api/users?page=10&per_page=100>; rel="last"

Возможные значения rel:

  • next — следующая страница результатов;
  • prev — предыдущая страница результатов;
  • first — первая страница результатов;
  • last — последняя страница результатов.

Важно следовать этим значениям, а не конструировать собственные URL-ы потому, что иногда постраничная навигация может основываться на сложных правилах, а не простом переборе страниц.

Переопределение HTTP-метода

Для совместимости с некоторыми серверами или клиентами, которые не поддерживают другие HTTP-методы кроме GET и POST, может быть полезным их эмуляция. Значение метода передаётся в заголовке X-HTTP-Method-Override, а сам он выполняется как POST-метод. GET-запросы не должны менять состояние сервера!

Коды HTTP-статуса

  • 200 OK — ответ на успешный запрос GET, PUT, PATCH или DELETE.
  • 201 Created — ответ на POST запрос, в результате которого произошло создание нового объекта. Ответ так же должен сопровождаться заголовком Location, указывающий на URL ресурса.
  • 204 No Content — ответ на успешно выполненный запрос, который ничего не возвращает (например, DELETE).
  • 404 Not Found — запрашиваемый объект не найден.
  • 500 Internal Server Error — ошибка на сервере.

В случае ошибок, в ответе может содержаться отладочная информация для разработчиков, если это возможно.

Метаданные

Любые данные, которые лишь опосредованно относятся к результату запроса, но могут быть полезны клиенту, стоит отдавать в виде HTTP-заголовков. Создание обёрток над данными ломает совместимость с принципами REST.