Денис Суворов 12 апреля 2022

😎✔️ 15 лучших практик разработки и проектирования REST API

Пятнадцать лайфхаков, которые сделают дизайн вашего REST API понятным и удобным.
😎✔️ 15 лучших практик разработки и проектирования REST API

1. Будьте последовательны

Звучит логично, но трудно правильно понять. API должно быть предсказуемым. Когда пользователь использует конечную точку и понимает ее, он ожидает, что другая конечная точка работает так же. Это показатель качества и удобства API.

  • Используйте один регистр для полей, ресурсов и параметров (например snake_case).
  • Используйте имена ресурсов в множественном или единственном числе: /users/{id}, /orders/{id} или /user/{id}, /order/{id}.
  • Используйте одинаковые методы авторизации и аутентификации для всех конечных точек.
  • Используйте одни и те же заголовки HTTP в API. Например, Api-Key для передачи ключа API.
  • Используйте одни и те же коды состояний HTTP в зависимости от типа ответа. Например, 404, когда ресурс не найден.
  • Используйте одни и те же методы HTTP для одних и тех же действий. Например, DELETE при удалении ресурса.

2. Используйте даты UTC по стандарту ISO 8601

Когда работаете с датой и временем, используйте формат ISO 8601. Отображение дат в конкретном часовом поясе – задача клиентских приложений.

        {
    "published_at": "2022-03-03T21:59:08Z"
}
    

3. Сделайте исключение для публичных конечных точек

Каждая конечная точка должна требовать авторизацию по умолчанию. Для вызова конечных точек требуется аутентифицированный пользователь, поэтому требование по умолчанию корректно. Если конечная точка вызывается публично, установите для нее разрешение на неавторизованные запросы.

4. Сделайте проверку работоспособности конечной точки

Создайте конечную точку (например, GET /health), которая определяет, работает ли служба. Эта конечная точка может вызываться другими приложениями, такими как балансировщики нагрузки, для действий в случае сбоя службы.

5. Версия API

Передавайте версию API при каждом запросе, чтобы пользователь не пострадал от изменений в другой версии. Версия API передается через HTTP-заголовок или параметры запроса/пути. Даже первая версия API должна иметь версию (1.0).

Примеры:

6. Принимать аутентификацию по ключу API

Если API вызывается третьей стороной, разрешите аутентификацию с помощью API ключей. API ключи передаются с помощью пользовательского заголовка HTTP (например, Api-Key). У ключей требуется предусмотреть срок действия и возможность отозвать активные ключи для аннулирования в случае компрометации. Избегайте проверку ключей API в пространстве управления исходным кодом (используйте переменные окружения).

7. Используйте разумные коды состояния HTTP

Используйте общепринятые коды состояния HTTP для объявления успеха или неудачи запроса. Не используйте слишком много кодов состояния и используйте одни и те же коды состояния для одних и тех же результатов во всем API.

Примеры:

  • 200 — общий успех.
  • 201 — успешное создание.
  • 400 — некорректный запрос от пользователя.
  • 401 — неавторизованный запрос.
  • 403 — отсутствие доступа.
  • 404 — недоступный ресурс.
  • 429 — слишком много запросов.
  • 5xx — для внутренних ошибок (следует избегать).

8. Используйте разумные методы HTTP

Основные HTTP методы:

POST GET PATCH PUT DELETE
Создание ресурсов Чтение ресурсов (как отдельных, так и списков) Применение частичных обновлений к ресурсу Применение полных изменений к ресурсу (заменяет текущий ресурс) Удаление ресурсов
POST /users GET /users PATCH /users/{id} PUT /users/{id} DELETE /users/{id}
GET /users/{id}

9. Используйте простые и понятные имена

Большинство конечных точек ресурсо-ориентированы и должны именоваться соответствующе. Не добавляйте ненужную информацию, доступную из других источников. То же касается и именования полей.

✅ Корректные:

  • GET /users — получить пользователей.
  • DELETE /users/{id} — удалить пользователей.
  • POST /users/{id}/notifications — создать уведомление для конкретного пользователя.
  • user.first_name
  • order.number

❌ Некорректные:

  • GET /getUsers
  • POST /updateUser
  • POST /notification/user
  • order.ordernumber
  • user.firstName

10. Используйте стандартизированные ответы на ошибки

Помимо использования кодов состояний HTTP, указывающих на результат запроса (успех или ошибка), при возврате ошибки используйте стандартизированный ответ об ошибке, включающий подробную информацию о том, что пошло не так. Это позволит потребителям рассчитывать на одинаковую структуру и действовать соответствующе.

        // Запрос => GET /users/4TL011ax
// Ответ <= 404 Не найдено

{
	“code”: “user/not_found”,
	“message”: “Не удалось найти пользователя с ID 4TL011ax.”
}

// Запрос => 
{
	“name”: “Иван Иванов”
}

// Ответ <= 400 Неверный запрос
{
	“code”: “user/email_required”,
	“message”: “Параметр [email] обязателен.”
}

    

11. Возвращайте созданные ресурсы после POST

Хорошей идеей является возврат созданного ресурса после его создания с помощью POST-запроса. Это важно, потому что возвращенный созданный ресурс будет отражать текущее состояние базового источника данных и содержать свежую информацию (например, сгенерированный ID).

        // Запрос: POST /users
{
	“email”: ”iivanov@averagecompany.com”,
	“name”: “Иван Иванов”
}

// Ответ
{
	“id”: “T9hoBuuTL4”,
	“email”: ”iivanov@averagecompany.com”,
	“name”: “Иван Иванов”
}

    

12. Предпочитайте PATCH вместо PUT

Запросы PATCH применяют частичные обновления к ресурсу, а PUT заменяют ресурс. Разработка обновлений на основе запросов PATCH предпочтительнее, потому что:

  • При использовании PUT для обновления только подмножества ресурса, требуется передавать весь ресурс, что повышает ресурсоемкость и вероятность ошибок.
  • Также опасно разрешать полю обновляться без ограничений.
  • Практический опыт показывает бессмысленность такого обновления ресурса.
  • Представьте ресурс с идентификатором и состоянием.
  • Опасно разрешать потребителям обновлять состояние заказа.
  • Изменение заказа скорее произойдет при вызове другой конечной точки (например, /orders/{id}/fulfill).

13. Будьте как можно конкретнее

Будьте корректным при разработке конечных точек, именовании полей и решении о том, какие запросы и ответы принимать. Если запрос PATCH принимает только два поля (имя и описание), то нет опасности неправильного использования запроса и повреждения данных.

14. Используйте пагинацию

Используйте пагинацию для запросов, возвращающих наборы ресурсов и используйте одну и ту же структуру ответа. Используйте page_number и page_size (или аналогичные) для управления тем, какую часть хотите получить.

        // Запрос => GET /users?page_number=1&page_size=15

// Ответ <= 200 OK

{
	“page_number”: 1,
	"page_size": 15,
	"count": 378,
	"data": [
        // resources
	],
	"total_pages": 26,
	"has_previous_page": true,
	"has_next_page": true
}

    

15. Разрешайте расширять ресурсы

Разрешите потребителям загружать связанные данные с помощью запроса expand (или аналогичного). Это полезно для избегания переходов туда-сюда и загрузки данных, необходимых для конкретного действия за раз.

        // Запрос => GET /users/T9hoBuuTL4?expand=orders&expand=orders.items

// Ответ <= 200 OK

{
  "id": "T9hoBuuTL4",
  "email": ”iivanov@averagecompany.com”,
  "name": “Иван Иванов”,
  "orders": [
    {
      "id": "Hy3SSXU1PF",
      "items": [
        {
          "name": "API курс"
        },
        {
          "name": "iPhone 13"
        }
      ]
    },
    {
      "id": "bx1zKmJLI6",
      "items": [
        {
          "name": "SaaS subscription"
        }
      ]
    }
  ]
}

    
***

Подводя итоги:

  • АПИ должно быть интуитивным.
  • Используйте формат ISO 8601 для дат.
  • Добавьте метод проверки работоспособности конечной точки.
  • Используйте версии API.
  • Используйте API ключи для аутентификации.
  • Используйте общепринятые коды состояний.
  • Используйте HTTP методы по назначению.
  • Уделите именованию внимание.
  • Используйте стандартные ответы HTTP.
  • Используйте пагинацию для списков.

Материалы по теме

Комментарии

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ