S3 REST API и метод POST

Я использую AWS S3 REST API, и после решения некоторых неприятных проблем с подписанием он, похоже, работает. Однако, когда я использую правильный глагол REST для создания ресурса, а именно POST, я получаю 405 method not allowed. Тот же запрос отлично работает с методом PUT и создает ресурс.

Я что-то делаю неправильно, или API AWS S3 REST не полностью совместим с REST?

Ответ 1

Да, вы ошибаетесь при сопоставлении методов CRUD с HTTP.

Несмотря на популярное использование и распространенное заблуждение, в том числе ответы с высоким рейтингом здесь, в Stack Overflow, POST не является "правильным методом для создания ресурса". Семантика других методов определяется протоколом HTTP, но семантика POST определяется самим типом целевого носителя. POST - это метод, используемый для любой операции, которая не стандартизирована по HTTP, поэтому ее можно использовать для создания, но также можно использовать для обновлений или чего-либо еще, что еще не сделано каким-либо другим способом. Например, неправильно использовать POST для извлечения, так как для этого у вас стандартизирован GET, но для использования ресурса, когда клиент не может использовать PUT, по какой-то причине он может использовать POST.

Таким же образом PUT не является "правильным методом обновления ресурса". PUT - это метод, используемый для полной замены ресурса, игнорируя его текущее состояние. Вы можете использовать PUT для создания, если у вас есть все представление, ожидаемое сервером, и вы можете использовать PUT для обновления, если вы предоставляете полное представление, включая части, которые вы не будете изменять, но не правильно использовать PUT для частичных обновлений, потому что вы просите серверу рассмотреть текущее состояние ресурса. Метод PATCH - это способ сделать это.

В неформальном языке каждый способ говорит серверу:

  • POST: возьмите эти данные и примените их к ресурсу, идентифицированному данным URI, следуя правилам, которые вы документировали для типа ресурса ресурса.

  • PUT: замените все, что идентифицируется данным URI, с этими данными, игнорируя все, что там уже есть, если что-нибудь.

  • PATCH: если ресурс, идентифицированный данным URI, все еще имеет такое же состояние, какое он имел в последний раз, когда я смотрел, примените этот diff к нему.

Обратите внимание, что создание или обновление не упоминается и не является частью семантики этих методов. Вы можете создавать с помощью POST и PUT, но не PATCH, поскольку это зависит от текущего состояния. Вы можете обновить любой из них, но с PATCH у вас есть обновление, зависящее от состояния, которое вы хотите обновить, с PUT, который вы обновляете, заменяя весь объект, так что это операция idempotent, и с помощью POST вы запрашиваете сервер это согласно предопределенным правилам.

Кстати, я не знаю, имеет ли смысл говорить, что API является или не является REST-совместимым, поскольку REST - это архитектурный стиль, а не спецификация или стандарт, но даже учитывая, что очень несколько API-интерфейсов, претендующих на REST, действительно RESTful, в большинстве случаев, потому что они не с гипертекстом. AWS S3 определенно не RESTful, хотя, где он имеет отношение к вашему вопросу, их использование HTTP-методов чаще всего выполняется по протоколу HTTP.

Ответ 3

Чтобы добавить к @Nicholos

Из http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

POST

Опубликованная сущность подчинена URI так же, как файл подчинен каталогу, содержащему его, новостная статья подчиненную группе новостей, на которую она отправлена, или запись подчиненный базе данных

Действие, выполняемое методом POST, может не привести к ресурсу которые могут быть идентифицированы с помощью URI. В этом случае либо 200 (OK), либо 204 (Без содержимого) - соответствующий статус ответа, в зависимости от того, или не ответ включает в себя объект, который описывает результат

Если ресурс был создан на исходном сервере, ответ СЛЕДУЕТ быть 201 (создан)

PUT

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

IMO PUT может использоваться для создания или изменения/замены закрытого объекта.

Ответ 4

+--------------------------------------+---------------------+
|                 POST                 |         PUT         |
+--------------------------------------+---------------------+
| Neither safe nor idempotent Ex: x++; | Idempotent Ex: x=1; |
+--------------------------------------+---------------------+