Должен ли HTTP PUT создать ресурс, если он не существует? - PullRequest
0 голосов
/ 21 мая 2019

Предположим, что кто-то выполняет PUT запрос моего конца:

/resources/{id}

Однако в моей базе данных PostgreSQL нет ресурса с данным идентификатором.

Согласно RFC 2616 , я должен создать ресурс, если я способен:

Метод PUT запрашивает, чтобы вложенный объект был сохранен под предоставленным Request-URI. Если Request-URI ссылается на уже существующий ресурс, вложенный объект СЛЕДУЕТ рассматривать как модифицированную версию, находящуюся на исходном сервере. Если Request-URI не указывает на существующий ресурс и этот URI может быть определен как новый ресурс запрашивающим пользовательским агентом, сервер-источник может создать ресурс с этим URI.

Можно ли создать ресурс с указанным идентификатором? Поскольку ручное назначение идентификаторов для вставки в базу данных не является наилучшей практикой.

Должен ли я возвращать ошибку 404, если создание ресурса невозможно?

Ответы [ 2 ]

5 голосов
/ 21 мая 2019

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

Цитата Марк Ноттингем , который на момент написания статьи являлся сопредседателем рабочих групп IETF HTTP и QUIC:

Не используйте RFC2616 . Удалите его со своих жестких дисков, закладок и запишите (или ответственно переработайте) все распечатанные копии.

Старый RFC 2616 был заменен следующими документами, которые вместе определяют протокол HTTP / 1.1:

Если вы ищете методы, коды состояния и определения заголовков, то RFC 7231 - это документ, к которому вы должны обратиться.


Сказав это, давайте вернемся к вашему вопросу.

Должен ли HTTP PUT создать ресурс, если он не существует?

Это зависит.

Но, если ваше приложение генерирует идентификаторы ресурсов от имени клиента, как вы упомянули в своем вопросе, вам следует использовать POST вместо PUT для создания Ресурсы.

Некоторые части определения метода PUT приведены ниже. Последнее предложение, кажется, наиболее актуально для вас (выделено мое), поддерживая то, что я только что упомянул выше:

4.3.4. PUT

Метод PUT запрашивает, чтобы состояние целевого ресурса было создано или заменено на состояние, определенное представлением, включенным в полезную нагрузку сообщения запроса. [...]

Если целевой ресурс не имеет текущего представления и PUT успешно создает его, сервер происхождения ДОЛЖЕН проинформировать агента пользователя, отправив ответ 201 (Создан). Если целевой ресурс действительно имеет текущее представление и это представление успешно изменено в соответствии с состоянием вложенного представления, то сервер-источник ДОЛЖЕН отправить ответ 200 (OK) или 204 (без содержимого) на указать успешное завершение запроса. [...]

Правильная интерпретация запроса PUT предполагает, что пользовательский агент знает, какой целевой ресурс требуется. Служба, которая выбирает правильный URI от имени клиента, после получения запроса на изменение состояния ДОЛЖНА быть реализована с использованием метода POST вместо PUT. [...]


Должен ли я возвращать ошибку 404, если создание ресурса невозможно?

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

6.5.4. 404 Не найдено

Код состояния 404 (не найден) указывает на то, что исходный сервер не нашел текущее представление для целевого ресурса или не желает раскрыть, что он существует. [...]


Теперь для полноты найдите ниже некоторые соответствующие цитаты об определении метода POST, которые следует использовать для создания ресурсов в сценарии, описанном в вашем вопросе:

4.3.3. POST

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

[...]

  • Создание нового ресурса, который еще не идентифицирован исходным сервером;

[...]

Если на исходном сервере был создан один или несколько ресурсов в результате успешной обработки запроса POST, исходный сервер ДОЛЖЕН отправить 201 (Создано)ответ, содержащий поле заголовка Location, которое предоставляет идентификатор для созданного первичного ресурса и представление, которое описывает состояние запроса при обращении к новому ресурсу (ам).

В то время как 201 код состояния указывает, что был создан новый ресурс, заголовок Location указывает, где находится вновь созданный ресурс.Если заголовок Location не предоставлен, то клиент должен предположить, что ресурс идентифицируется URI действующего запроса:

6.3.2.201 Создан

Код состояния 201 (Создан) указывает, что запрос был выполнен и привел к созданию одного или нескольких новых ресурсов.Основной ресурс, созданный запросом, идентифицируется либо полем заголовка Location в ответе, либо, если поле Location не получено, эффективным URI запроса.[...]

1 голос
/ 21 мая 2019

Короче говоря, это зависит от того, какая полезная нагрузка, которую вы хотите сохранить, нарушает любые ограничения сервера на ресурсы или нет.

В общем, я бы сказал, что следует попытаться, поскольку клиент явно выражает свое намерение сохранить это конкретное представление в целевом URI.Сервер должен хотя бы выполнить проверку ограничений раньше!Обычно в реальном сценарии REST клиент должен использовать URI, предоставленный сервером, а не просто выбирать какой-либо URI сам по себе.Таким образом, сервер должен контролировать свое пространство имен, так как использование по умолчанию PUT для создания ресурсов здесь не рекомендуется.

С учетом сказанного, поскольку PUT является идемпотентом, а POST не так, некоторые клиенты могут захотеть воспользоваться этой собственностью.Здесь развился шаблон создания POST-PUT , где клиент пытается создать новый ресурс через POST, пока не получит подтверждение через заголовок Location в ответе, а затем попытается обновитьсостояние этого ресурса через PUT.Таким образом, клиент может быть уверен, что в случае проблем с передачей представление было создано только один раз.В зависимости от позиции некоторые люди могут рассматривать фактическое обновление ресурса как фактическое создание ресурса, хотя, поскольку клиент заранее получил соответствующую ссылку, это не совсем так.

Обратите внимание, что сервер также имеетправо преобразовывать представление во что-то другое, если, например, сервер сконфигурирован для предоставления конкретных представлений для определенных конечных точек URI.Подумайте о загрузке изображения через PUT в URI, и сервер встроит изображение в HTML-страницу

...