Что фиксируется в контракте api согласно стандарту
Перейти к содержимому

Что фиксируется в контракте api согласно стандарту

  • автор:

Api — готовим правильно

API это хорошо реализованный процесс работы с сервисом, котор может сильно ускорить интеграцию с с сервисом.

В сети сейчас представлен ряд готовых инструментов, которые умеют делать API и работать с ним. Однако, как показывает практика, они часто избыточны (реализация отнимает слишком много времени разработчика, тимлида, архитектора).

Выбор решения

В настоящий момент, хорошим решением реализации API может быть GraphQL, но его недостаточно, потому что его идеология построена на:

  • Доменная модель (модели и поля)
  • Доступ к скоупам/функциям-наборам/функциям-экшенам модели (сложные выборки, сортировки, группировки)
  • Работа с выше перечисленным на уровне написания SQL-подобного синтаксиса в виде графа

А вот список того, что GraphQL не покрывает, но без этого никуда

  • Доступ к сервис-классам (классам, которые имплементируют себя в виде сервиса бизнес-логики или внешнего сервиса)
  • Администрирование доступа API-клиентов (разграничение доступа к выше перечисленному)
  • Администрирование API-клиентов (непосредственно клиенты, токены, лимиты запросов и т.п.)
  • Авто-документирование API (желательно OAS 3, желательно на основе описания анотаций в коде или YAML)
  • Расширение API-функционала поддерживающее совместимость прежних версий

Что нужно клиенту

Клиент — приложение, которое взаимодействует с Вашим API, и вот что ему нужно:

  • Транзакционность запросов
  • Контракт — формальное описание договоренностей взаимодействия клиента и сервера (API). Контракт можно расширять, но нельзя изменять, таким образом требуется поддерживать обратную совместимость. Если необходимо нарушить контракт, то пишут новую версию API. В контракт обязаны быть заложены ошибки клиента (4ХХ)

У клиента есть обязанности:

  • клиент обязан уметь обрабатывать все возможные HTTP-коды, в том числе 5ХХ
  • клиент обязан уметь обрабатывать X-Header, которым сервер говорит, что на сервере проходит процесс обновления (сервера или приложения)
  • если API работает в READ only режиме, то клиент не должен ломаться

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

Напомню, что сейчас довольно широко распространен подход REST и RESTful, о том, как его хорошо приготовить, я напоминаю ниже.

REST реализация

Чтобы реализовать данный подход, нужен отдельный фронт-контроллер, ниже я излагаю требования к нему.

1. Новый API фронт-контроллер должен:

  • как в крупных компаниях, следовать rest (get,post,put,patch,delete) — https://blog.octo.com/en/design-a-rest-api/
  • автоматически уметь работать с любой моделью (желательно без создания объектов)
  • иметь авто-роутинг моделей, в том числе с пагинацией двух видов:
    • клиент указывает только page_number и page_rows, /v1/restaurants?page=0-24
    • клиент указывает offset – limit, пример /v1/restaurants?range=0-24

    2. Тип возвращаемых данных может отдаваться согласно указанному типу, в таком приоритете:

    • формат указан в заголовке, например ‘Content-Type: application/json’
    • формат указан в расширении урл, например: https://stream.twitter.com/1.1/statuses/sample.json
    • по-умолчанию json

    3. Версионность ни к чему не привязана, т.е. может инкрементироваться как-угодно под каждый роут, однако, версию надо указывать вначале роутинга, например:

    • было: /api/v1.1/sample.json
    • стало: /api/v2/sample.json

    4. Параметры в крупных компаниях именуют в snake_case. Думаю, нам стоит тоже так делать, даже не смотря на плюс кэмелкейса (удобно мапить передаваемые поля на поля моделей, реквеств-объектов), ведь:

    • есть свагер и благодаря анотации может мапить как душе угодно (snake -> camel)
    • можем сделать функцию конвертации именования параметров, а для нового фронт-контроллера делать это по-умолчанию

    5. Частичный ответ, должен уметь работать при любом типе запроса, например: /clients/007?fields=firstname,name,address

    • модели должны уметь поднимать данные частично
    • если запрос идет не к моделе, то хорошо бы реализовывать обработчики запросов, которые будут уметь «частичный ответ»

    6. Поиск (фильтрация), должен уметь работать при любом типе запроса, например: /v1/restaurants/search?name=napoli*&type=chinese-or-japanese-and-italian и так далее:

    'attribute:value AND | OR | NOT attribute:value' 'numeric_attribute = | != | > | >= | < |  

    7. Сортировка, должна уметь работать при любом типе запроса, например: /v1/restaurants?sort=rating,reviews-desc,name-ask

    В настоящий момент не продуманы моменты:

    • Авторизация клиента (что является публичным роутом, а что нет)
    • Доступ клиентов к полям моделей (например пароли, паспортные данные) будет реализован позже (возможно нужна будет админка или настройка доступа на уровне бд - но тут есть момент: внутренние системы с данными)
    • Вложенность данных (данные реляций)
    • В большинстве случаев HTTP-статус 422 приравнивают к 400 (т.е. 422 нет), стоит ли нам тоже так делать, или нет

    Еще, хотелось бы напомнить про некоторые нюансы.

    Response

    Response не должен быть пустым, потому что в случае CORS запросов, браузеры по умолчанию могут получить доступ только к следующим заголовкам ответа:

    • Cache-Control
    • Content-Language
    • Content-Type
    • Expires
    • Last-Modified
    • Pragma

    Если требуется, чтобы клиентское приложение получило доступ к другим заголовкам, необходимо чтобы серер отдавал заголовок:

    Access-Control-Expose-Headers: Access-Token, Uid

    REST

    Таблица рекомендуемых возвращаемых значения основных методов HTTP в сочетании с URI ресурсов:

    HTTP Verb CRUD Entire Collection (e.g. /customers) Specific Item (e.g. /customers/)
    POST Create 201 (Created), 'Location' header with link to /customers/ containing new ID. 404 (Not Found), 409 (Conflict) if resource already exists..
    GET Read 200 (OK), list of customers. Use pagination, sorting and filtering to navigate big lists. 200 (OK), single customer. 404 (Not Found), if ID not found or invalid.
    PUT Update/Replace 405 (Method Not Allowed), unless you want to update/replace every resource in the entire collection. 200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid.
    PATCH Update/Modify 405 (Method Not Allowed), unless you want to modify the collection itself. 200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid.
    DELETE Delete 405 (Method Not Allowed), unless you want to delete the whole collection—not often desirable. 200 (OK). 404 (Not Found), if ID not found or invalid.
    Разницу (отличия) между PUT и PATCH

    Представьте, что у вас на сайте публикуются статьи. У статей есть заголовок и содержание, которые вы можете редактировать.

    PUT /articles/12
    PATCH /articles/12

    Итог: PUT и PATCH cработают идентично.

    Вариант 2: вы изменяете только заголовок.

    PUT /articles/12
    PATCH /articles/12
    • PUT изменит заголовок title и очистит поле content , потому что вы его не передали ( PUT меняет объект целиком).
    • PATCH изменит только заголовок title , не трогая поля content , потому что вы его не передали ( PATCH изменяет отдельные поля ресурса).

    Источник: 1 - 2 Готовые решения: StrAPI (админка с автоматически создаваемым API с автоматически генерируемым сваггером)

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *