2013-11-07 4 views
39

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

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

ответ

166

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

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

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

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

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

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

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

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

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

+1

Хорошее объяснение. POST изменяет ресурс. Люди путаются, потому что для POST обычно используется ресурс, представляющий коллекцию для изменения коллекции, создавая новый член. Но новый член - это другой ресурс с другим URL-адресом, чем тот, с которым вы отправили сообщение. –

+1

Интересно, я не знал, что большинство источников я проверил разговоры о картировании CRUD для POST, GET, PUT, DELETE. Хотя я обнаружил, что некоторые из них заявили, что это POST для '/ someobjects /' vs PUT для '/ someobjects/identifier'. Который имел бы смысл, почему S3 API жалуется, поскольку я делаю POST в '/ path/file.name'. – vartec

+0

Если вы создаете POST в /path/file.name, пытающемся создать этот ресурс, это определенно неверно, поскольку данные POST подчинены ресурсу /path/file.name, а если не существует, он не может что-нибудь с этим делать. Теоретически AWS должен вернуть 404, а не 405, но это, вероятно, деталь реализации.Маршрут для него имеет разрешенные методы, и он проверяет этот метод, прежде чем проверять, действительно ли ресурс существует. –

1

В the original HTTP specification ресурс, указанный в полезной нагрузке запроса POST, считается «подчиненным указанному объекту» (то есть URL-адрес запроса). TimBL сказал ранее (не может найти ссылку), что он был смоделирован на the identically-named method in NNTP.

1

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

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

POST:

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

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

Если ресурс был создан по происхождению сервер, ответ ДОЛЖЕН быть 201 (Созданный)

PUT:

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

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

2
+--------------------------------------+---------------------+ 
|     POST     |   PUT   | 
+--------------------------------------+---------------------+ 
| Neither safe nor idempotent Ex: x++; | Idempotent Ex: x=1; | 
+--------------------------------------+---------------------+ 
Смежные вопросы