Подтвердить что ты не робот

Избегайте дублирования POST с REST

Я использую POST в REST API для создания объектов. Время от времени сервер будет создавать объект, но клиент будет отключен, прежде чем получит ответ 201 Created. Клиент видит только неудачный запрос POST и повторяет попытку позже, и сервер с радостью создает дублирующий объект...

У других, должно быть, была эта проблема, верно? Но я google вокруг, и все просто, кажется, игнорируют это.

У меня есть 2 решения:

A) Вместо этого используйте PUT и создайте ID (GU) на клиенте.

B) Добавьте GUID ко всем объектам, созданным на клиенте, и обеспечьте, чтобы сервер выполнял их UNIQUE -ness.

A не соответствует существующим фреймворкам очень хорошо, и B выглядит как хак. Как другие люди решают это, в реальном мире?

Edit:

С помощью Backbone.js вы можете установить идентификатор GUID в качестве идентификатора при создании объекта на клиенте. Когда он будет сохранен, Backbone выполнит запрос PUT. Сделайте REST backend handle PUT для несуществующих идентификаторов, и вы настроены.

4b9b3361

Ответ 1

Я всегда использую B - обнаружение дубликатов из-за того, что проблема принадлежит серверной стороне.

Ответ 2

Другим решением, которое было предложено для этого, является POST Once Exactly (POE), в котором сервер генерирует одноразовые POST-URI, при использовании более одного раза, сервер запустит ответ 405.

Недостатком является то, что 1) проект POE был продлен без какого-либо дальнейшего прогресса в области стандартизации, и, следовательно, 2) его внедрение требует изменений в клиентах для использования новых заголовков POE и дополнительной работы серверов для реализации Семантика POE.

По googling вы можете найти несколько API, которые его используют, хотя.

Еще одна идея, которую я имел для решения этой проблемы, - это условный POST, который я описал, и попросил отклик на здесь.

Кажется, нет единого мнения о том, как предотвратить дублирование создания ресурсов в случаях, когда уникальное поколение URI не может быть PUT на клиенте, и поэтому необходим POST.

Ответ 3

Вы можете попробовать двухэтапный подход. Вы запрашиваете создание объекта, который возвращает токен. Затем во втором запросе запросите статус, используя токен. Пока запрос статуса не будет использован с использованием токена, вы оставите его в "поэтапном" состоянии.

Если клиент отключается после первого запроса, у него не будет токена, и объект остается "поставленным" на неопределенный срок или пока вы не удалите его другим процессом.

Если первый запрос завершен успешно, у вас есть действительный токен, и вы можете захватить созданный объект столько раз, сколько хотите, без его воссоздания.

Нет причин, по которым токен не может быть идентификатором объекта в хранилище данных. Вы можете создать объект во время первого запроса. Второй запрос действительно просто обновляет "поэтапное" поле.

Ответ 4

Обнаружение дубликатов - это kludge, и может стать очень сложным. Подлинные, но похожие запросы могут поступать одновременно, возможно, из-за восстановления сетевого соединения. И повторные запросы могут прибывать в часы или дни друг другу, если сетевое соединение выпадает.

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

Простой и надежный шаблон для решения этой проблемы заключается в следующем: серверные приложения должны хранить все ответы на небезопасные запросы, а затем, если они видят дублированный запрос, они могут повторять предыдущий ответ и ничего не делать. Сделайте это для всех небезопасных запросов, и вы решите кучу тернистых проблем. "Дубликат" определяется идентификатором уровня приложения, либо сгенерированным клиентом GUID, либо с номером последовательности, генерируемым сервером. В этом втором случае запрос-ответ должен быть посвящен только обмену идентификатором. Мне нравится это решение, потому что выделенный шаг заставляет клиентов думать, что они получают что-то ценное, что им нужно ухаживать. Если они могут генерировать свои собственные идентификаторы, они с большей вероятностью помещают эту строку в цикл, и каждый кровавый запрос будет иметь новый идентификатор.

Используя эту схему, все POST являются пустыми, а POST используется только для получения идентификатора действия. Все PUT и DELETE полностью идемпотентны: последовательные запросы получают одинаковый (сохраненный и воспроизводимый) ответ и не приводят к дальнейшему дальнейшему его возникновению. Самое приятное в этом плане - качество Kung-Fu (Panda). Требуется слабость: склонность клиентов повторять запрос в любое время, когда они получают неожиданный ответ, и превращает его в силу: -)

У меня есть небольшой google doc здесь, если кому-то это нужно.

Ответ 5

Идентификаторы с сервером

Если вы имеете дело с случаем, когда это сервер, который выдает идентификаторы, создайте объект во временном, поэтапном состоянии. (Это неотъемлемая операция без idempotent, поэтому это должно быть сделано с помощью POST.) Затем клиенту необходимо выполнить дальнейшую операцию, чтобы перенести его из поэтапного состояния в активное/сохраненное состояние (которое может быть PUT свойство ресурса или подходящий POST для ресурса).

Каждый клиент должен каким-либо образом (возможно, смешанным с другими ресурсами) собирать список своих ресурсов в поэтапном состоянии и должен УДАЛИТЬ ресурсы, которые они создали, если они все еще просто поставлены. Вы также можете периодически удалять поэтапные ресурсы, которые в течение некоторого времени были неактивными.

Вам не нужно показывать один клиентский поэтапный ресурс любому другому клиенту; они должны существовать глобально только после подтверждения.

Идентификаторы, выданные клиентом

Альтернативой является выдача клиентом идентификаторов. Это в основном полезно, когда вы моделируете что-то вроде filestore, поскольку имена файлов обычно значимы для кода пользователя. В этом случае вы можете использовать PUT для создания ресурса, поскольку вы можете сделать все это идемпотентно.

Нижняя сторона этого заключается в том, что клиенты могут создавать идентификаторы, и поэтому у вас нет контроля над всеми идентификаторами, которые они используют.