2010-08-11 2 views
6

Часть нашего RESTful API позволит пользователям регистрировать элемент с серийным номером. Поскольку серийный номер не уникален глобально, он не может использоваться как идентификатор ресурса, поэтому мы будем использовать POST для родительского ресурса, который будет генерировать идентификатор, например.Реагирование на идемпотентный запрос HTTP POST

POST /my/items 

<item serial-number="ABCDEF" /> 

В случае если элемент еще не зарегистрирован, семантика HTTP четко определена. Мы возвращаем заголовок Location и зарегистрированный элемент как тело объекта, например.

HTTP 201 Created 
Location: /my/items/1234  

<item id="1234" serial-number="ABCDEF" /> 

Однако, в том случае, когда элемент уже зарегистрирован, то API должен быть идемпотентным и вернуть ранее зарегистрированный элемент, не создавая новый. Я полагаю, что он должен вернуть код состояния 200 OK и использовать заголовок Content-Location, чтобы указать, откуда пришел элемент, например.

HTTP 200 OK 
Content-Location: /my/items/1234  

<item id="1234" serial-number="ABCDEF" /> 

Было ли это разумным? Я не совсем понимаю, подходит ли Location или Content-Location во втором случае.

ответ

7

У меня было аналогичное требование в последнее время. Для идемпотентных операций PUT - лучший способ. Вы правы, существует несоответствие между внешним и внутренним. Я решил, создав специальный ресурс для целевого внешнего ID:

PUT /api-user/{username}/items/{serialNumber} 

Внутренне я решаю его как CREATE в случае, если у меня нет пункта для «Имя пользователя» и серийный номер «ABCDEF» или UPDATE в случае, если я делаю ,

В случае, если это был CREATE, я возвращаю 201 для UPDATE 200. Кроме того, возвращаемая полезная нагрузка содержит как внутренний код, так и внешний серийный номер, как вы указали в своей полезной нагрузке.

+0

Хм, да, на самом деле мне это нравится. Хотя серийные номера не могут быть глобально уникальными, существует почти 100% вероятность того, что они будут уникальными в рамках пользователя, поэтому он может действовать как уникальный идентификатор с областью. Это также решит мою проблему о том, как устройство может проверить, уже ли оно зарегистрировано, используя GET на этом URL-адресе и проверяя, является ли ответ 200 или 404. Спасибо! –

1

Here - интересная дискуссия об использовании двух заголовков. Он утверждает, что Content-Location не определен для PUT или POST, поэтому расположение, возможно, является лучшим вариантом в вашем случае. Это, конечно, не четкое сокращение, которое лучше, хотя.

В целом я думаю, что ваш подход имеет смысл.

+0

В этой статье отсутствует бит, когда указано, что Content-Location не задано для PUT и POST, спецификация HTTP фактически говорит, что она не определена для запросов, но ничего не говорит об ответах. Я думаю, что это может быть правильно, хотя в том, что Content-Location предназначен для альтернативных форм, тогда как Location - это фактическое местоположение. Трудно быть уверенным в спецификации: -S –

Смежные вопросы