Я работаю над REST API. Ключевые объекты («существительные») являются «элементами», и каждый элемент имеет уникальный идентификатор. Например. получить информацию о товаре с идентификатором foo:
GET http://api.example.com/v1/item/foo
Новые элементы могут быть созданы, но клиент не может выбрать идентификатор. Вместо этого клиент отправляет некоторую информацию, которая представляет этот элемент. Итак, чтобы создать новый предмет:
POST http://api.example.com/v1/item/
hello=world&hokey=pokey
С помощью этой команды сервер проверяет, есть ли у нас элемент для информации hello=world&hokey=pokey
. Итак, здесь есть два случая.
Случай 1: предмет не существует; это создано. Этот случай прост.
201 Created
Location: http://api.example.com/v1/item/bar
Случай 2: предмет уже существует. Вот где я борюсь ... не уверен, какой код перенаправления лучше всего использовать.
301 Moved Permanently
? 302 Found
? 303 See Other
? 307 Temporary Redirect
Location: http://api.example.com/v1/item/foo
Я изучил описания Википедии и RFC 2616 , и ни одно из них не кажется идеальным. Вот конкретные характеристики, которые я ищу в этом случае:
Перенаправление является постоянным, поскольку идентификатор никогда не изменится. Таким образом, для эффективности клиент может и должен направлять все будущие запросы к конечной точке идентификатора напрямую. Это говорит о 301, так как остальные три должны быть временными.
Перенаправление должно использовать GET, даже если этот запрос POST. Это предполагает 303, поскольку все остальные технически должны повторно использовать метод POST. На практике браузеры будут использовать GET для 301 и 302, но это REST API, а не веб-сайт, предназначенный для использования обычными пользователями в браузерах.
Это должно быть широко доступно и легко играть. В частности, 303 - это HTTP / 1.1, тогда как 301 и 302 - это HTTP / 1.0. Я не уверен, насколько это серьезная проблема.
На данный момент, я склоняюсь к 303 только для того, чтобы быть семантически правильным (используйте GET, не повторяйте POST) и просто поглощайте его во «временной» части. Но я не уверен, что 302 будет лучше, так как на практике это было то же поведение, что и 303, но без использования HTTP / 1.1. Но если я пойду по этой линии, мне будет интересно, будет ли 301 еще лучше по той же причине плюс «постоянная» часть.
Мысли приветствуются!
Редактировать: Позвольте мне попытаться лучше объяснить семантику этой операции "получить или создать" на более конкретном примере: сокращение URL. Во всяком случае, это намного ближе к моему приложению.
Для укорачивателей URL наиболее распространенной операцией на сегодняшний день является получение по идентификатору Например. для http://bit.ly/4Agih5, bit.ly получает идентификатор 4Agih5 и должен перенаправить пользователя на соответствующий ему URL.
bit.ly уже имеет API, но это не совсем RESTful. Для примера позвольте мне создать более RESTful API. Например, запрос идентификатора может вернуть всевозможную информацию о нем (например, аналитика):
GET http://api.bit.ly/item/4Agih5
Теперь, если я хочу отправить новый URL-адрес для сокращения bit.ly, я заранее не знаю идентификатор своего URL-адреса, поэтому я не могу использовать PUT. Я бы вместо этого использовал POST.
POST http://api.bit.ly/item/
url=http://stackoverflow.com/
(но закодировано)
Если bit.ly раньше не видел этот URL, он создаст для него новый идентификатор и перенаправит меня через 201 Created на новый идентификатор. Но если он видел этот URL, он все равно перенаправит меня без внесения изменений. Таким образом, я могу попасть в это место перенаправления, чтобы получить информацию / метаданные по сокращенному URL.
Как и в этом примере сокращения URL, в моем приложении коллизии не имеют значения. Один URL-адрес соответствует одному идентификатору, и все. Так что на самом деле не имеет значения, был ли URL сокращен раньше или нет; в любом случае, имеет смысл указать клиенту идентификатор для него, нужно ли сначала создавать этот идентификатор или нет.
Так что я, вероятно, не буду менять этот подход; Я просто спрашиваю о лучшем методе перенаправления для него. Спасибо!