Какова стандартная практика разработки REST API, если он используется для вставки/обновления списка записей?

Мы создаем API, который будет использоваться для вставки и обновления записей в базе данных. Поэтому, если запись существует на основе ключа, запись будет обновлена, а если нет, то она будет вставлена.

У меня есть два вопроса.

  • В соответствии с рекомендациями REST, каковы варианты разработки такого API, например. ПОСТАВИТЬ/ПОСТАВИТЬ ИЛИ ПАТЧИТЬ? Как должен быть представлен список объектов? ПРИМЕЧАНИЕ. Из других ответов, которые я читал, я знаю, что существует путаница в отношении того, как это должно быть в соответствии с рекомендациями REST. Так что я в порядке, если я могу получить некоторые рекомендации по общей передовой практике (независимо от части REST)
  • Во-вторых, часть, в которой я действительно запутался, - это то, как представить вывод этого или что должен возвращать этот API.

Буду очень признателен за конкретные рекомендации/вклады по вышеуказанной теме.


person Jags    schedule 25.01.2019    source источник
comment
Что касается вашего второго вопроса, в архитектуре REST клиенты должны отправлять заголовок Accept, информирующий сервер о том, какой тип мультимедиа поддерживает клиент, и сервер должен выбрать тот, который наиболее подходит для ресурса. application/json в целом является плохим медиа-типом для REST, поскольку он не намекает клиенту ни на какие доступные ссылки, ни на какой тип содержимого на самом деле. Просто легко попасть в типизированные ресурсы перехватывают и предполагают, что ресурс имеет тип, что неверно с точки зрения REST.   -  person Roman Vottner    schedule 25.01.2019
comment
... хотя, если вас не очень интересует архитектура REST, а просто расплывчатая вещь, которую большинство разработчиков понимают как REST (модное слово), вам решать, как вы ответите. Вы можете проверить, есть ли определенные типы мультимедиа, которые уже отображают смысл контента. т.е. счета-фактуры могут быть представлены во многих формах, на основе XML, EDIFACT, ZUGFeRD/PDF, ...   -  person Roman Vottner    schedule 25.01.2019


Ответы (1)


Я видел много разных реализаций вставок/обновлений от разных поставщиков (Stripe, HubSpot, PayPal, Google, Microsoft). Несмотря на то, что они различаются, эта разница каким-то образом хорошо согласуется с их общей реализацией API и обычно не вызывает стресса.


При этом «общее» правило для вставок таково:

POST /customers - укажите данные клиента в body.

Это создаст нового клиента, вернет уникальный идентификатор и сведения о клиенте в ответе (вместе с createdDate и другими автоматически сгенерированными атрибутами).

Почти все, если не все поставщики API, реализуют эту логику для вставок.


Обновления совсем другие. Ваши варианты включают в себя:

РАЗМЕСТИТЬ

POST /customer/<customer_id> — включите атрибуты и значения, которые вы хотите обновить в теле.

Здесь вы используете POST для обновления клиента. Это не очень распространенная реализация, но я видел ее в нескольких местах.

ВСТАВИТЬ

PUT/customer/<customer_id> - включить в тело либо все, либо частично обновленные атрибуты.

Учитывая, что PUT технически является идемпотентным методом, вы можете либо оставаться верным соглашению REST и ожидать, что ваши пользователи предоставят все атрибуты для обновления ресурса, либо упростить его, приняв только те атрибуты, которые они хотят обновить. Второй вариант не очень «RESTful», но с ним проще работать с точки зрения пользователя (и он уменьшает размер полезной нагрузки).

ИСПРАВЛЕНИЕ

PATCH /customer/<customer_id> — включает операцию и атрибуты, которые вы хотите обновить/удалить/заменить/и т. д. в теле. Подробнее о том, как ИСПРАВИТЬ .

Метод PATCH используется для частичных обновлений, и именно так вы «предназначены» для вызова частичных обновлений. Это немного сложнее использовать с точки зрения потребителей.

Вот тут-то и срабатывает предвзятость. Я лично предпочитаю использовать POST, где мне не требуется предоставлять все атрибуты для запуска обновления (только те, которые я хочу обновить). Причина в простоте использования.

Что касается тела ответа для обновлений, обычно они возвращают объект в теле ответа, включая обновленные атрибуты (и обновленные автоматически сгенерированные атрибуты, такие как updatedDate).


Массовые вставки/обновления

Глядя на API Facebook Graph HTTP (пакетный запрос) для вдохновения, и предполагая, что POST является вашим предпочтительным методом для обновлений, вы можете внедрить массив запросов, используя в качестве опции выделенный ресурс batch.

Конечная точка: POST /batch/customers

Тело:

{
   ["first_name": "John", "last_name": "Smith"...], //CREATE
   ["id": "777", "first_name": "Jane", "last_name": "Doe"...], //UPDATE
   ["id": "999", "first_name": "Mike", "last_name": "Smith"...], //UPDATE
   [....]
}

Пример ответа

{
  "id": "123",
  "result":[
      { // Creation successful
        "code": 200,
        "headers":{..},
        "body": {..},
        "uri": "/customers/345"
      },
      { // Update successful
        "code": 200,
        "headers":{..},
        "body": {..},
        "uri": "/customers/777",
      },
      { // A failed update request
        "code": 404,
        "headers":{..},
        "body": {..}, // body includes error details
      }
  ]
}
person Mo A    schedule 25.01.2019
comment
Согласно RFC 7231 PUT следует заменить только весь контент. В этом разделе есть примечание, в котором разъясняется, как можно добиться частичного обновления (PATCH или обновить ресурс, который частично перекрывает другой ресурс, для другого ресурса это имеет эффект частичного обновления), но его НЕ следует использовать для отправлять на сервер только частичные данные! - person Roman Vottner; 25.01.2019
comment
Далее PATCH также не является операцией, при которой можно отправлять только интересующие вас атрибуты . Вы можете прочитать как правильно патчить. При этом на самом деле существует формат JSON Merge Patch, который, вероятно, близок к тому, что вы предложить, хотя это должно быть согласовано между клиентом и сервером (в архитектуре REST), иначе сервер может не понять, что запрашивает клиент - person Roman Vottner; 25.01.2019
comment
Привет @RomanVottner, я согласен с тем, что PATCH — это правильный способ частично обновить ресурс с использованием принципалов REST. Я просто указал параметры, которые доступны в настоящее время, и то, как существующие API позволяют выполнять обновления сегодня. Если выбор состоит в том, чтобы строго следовать REST, то PATCH это так. Спасибо, что поделились ссылками. На самом деле то, что я хотел описать выше, это то, что он также должен включать операцию в PATCH, а не включать ее в тело как POST/PUT - обновит ответ. - person Mo A; 25.01.2019
comment
Я понимаю обсуждение, но вопрос конкретно в том, как это работает в случае списка объектов - person Jags; 25.01.2019
comment
@Jags извините, я упустил суть! Я обновил ответ, включив в него предложение по созданию/обновлению массовых объектов. - person Mo A; 25.01.2019