2009-05-08 4 views
43

Для сайта, над которым я работаю, мы улучшаем наши URL-адреса для одного типа ресурсов - в частности, отступая от числовых идентификаторов к уникальным описательным строкам. Аналогичным примером может быть переход от идентификации пользователей по числовому идентификатору базы данных для идентификации их по имени пользователя (а не в нашем конкретном случае, но аналоговом). Таким образом, URL, чтобы получить доступ к информации пользователя, используемый выглядеть следующим образом:REST - поддержка нескольких возможных идентификаторов

/users/48573 

И теперь, похоже,

/users/thisisausername. 

Единственная проблема заключается в том, что нам все еще нужно, чтобы иметь возможность получать их через численные идентификаторы как-то , для устаревших потребителей API. Нам не нужны сами URL-адреса REST для перенаправления (например, /users/48573 не следует перенаправлять на /users/thisisausername), нам просто нужен метод для получения правильных данных с использованием старого идентификатора. Решение должно либо предоставить альтернативный способ доступа к информации пользователя (который удобно включает в себя новый идентификатор, имя пользователя) по идентификатору, либо получить доступ только к имени пользователя по идентификатору. Возможными решениями могут быть:

  • Использование узла для указания некоторого альтернативного способа идентификации, например. /users/byid/48573
  • Использование параметра запроса для указания некоторого альтернативного способа идентификации, например. /users/48573?fetchby=id или /users/48573?byid=true
  • Рассмотрение имени пользователя по-одному в качестве другого ресурса, например. /identifiers/username/48573

Какой из них (если есть) является самым близким к надлежащему REST? Как бы вы справились с этой проблемой?

+4

Я кончался осуществление доступа через полей неглавный-идентификатор в качестве поиска. Это решение позволяет извлекать несколько типов ресурсов через несколько полей, сохраняя при этом только один в качестве основного идентификатора. Для согласованности списки API поиска «поиск». Таким образом, официальный способ доступа пользователя является: /пользователя/thisisausername и доступ ID, мы имеем: /пользователей идентификатора = 48573 Аналогично, мы могли бы поиск по целому ряду различных областей , как в: /users? firstName = Kelly Вдохновение было: http://jwyseur.blogspot.com/2008/12/uri-design-for-rest.html (см. «поиск ресурса») –

+0

Итак, вы набросились на кеширование? У меня такая же проблема, как у вас, но не могу решить проблему с помощью параметров запроса, которые устраняют одно из основных преимуществ REST API. Мне нравится ваше первое рекламное предложение ... – HDave

ответ

10

Ваш первый вариант, вероятно, лучший.

Поиск пользователей по ID:

/users/id/48573 

Поиск пользователей по короткому имени:

/users/name/thisisausername 

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

Другой вариант, который я видел совсем немного, чтобы использовать параметры запроса, как следующее:

/users?id=48573 
/users?name=thisisausername 

Я думаю, что первый выглядит немного чище и более удобным для чтения.

+0

короткое и точное, отлично! –

-3

Я бы рассмотреть квалификационные строки с дополнительным суффиксом:

/users/48573/id 

/users/48573/name 

Если вы получите строку без суффикса:

/users/48573 

то проверить строку и посмотреть, если это идентификатор или имя.

Если вы только получить действительное удостоверение личности, но не имя, то это поиск по ID эквивалентно:

/users/48573/id 

Если вы только получить имя тогда это поиск по имени, эквивалентном:

/users/48573/name 

Если вы можете получить значение по ID или имя, то вы возвращаете ошибку в 300 Ответную ссылки на оба идеи! клиент:

/users/48573/id 

/users/48573/name 

Наследственные потребители продолжают работать «как есть», за исключением случайного появления повторяющихся пар ID/name, где они получают новую ответную ошибку 300.

+7

Это не ОТДЫХ. Это просто RPC. – aehlke

-3

Ваш API не является RESTful, если это проблема. До quote Roy Fielding:

REST API не должен определять фиксированные имена ресурсов или иерархии (очевидное соединение клиента и сервера). Серверы должны иметь свободу контролировать свое пространство имен. Вместо этого разрешите серверам указывать клиентам, как создавать соответствующие URI, например, в HTML-формах и шаблонах URI, определяя эти инструкции в типах медиа и связных отношениях. [Сбой здесь означает, что клиенты принимают структуру ресурсов из-за внеполосной информации, такой как стандарт, специфичный для домена, который является ориентированным на данные эквивалентом функциональной связи RPC].

REST API должен быть введен без предварительного знания за пределами первоначального URI (закладки) и набора стандартных типов медиа, которые подходят для целевой аудитории (то есть ожидается, что их понимает любой клиент, который может использовать API) , С этого момента все переходы состояния приложения должны управляться выбором клиентом предоставленных сервером вариантов, присутствующих в полученных представлениях или подразумеваемых манипуляциями пользователя с этими представлениями. Переходы могут быть определены (или ограничены) знаниями клиента о типах медиа и механизмах обмена ресурсами, которые могут быть улучшены «на лету» (например, код по требованию). [Ошибка здесь подразумевает, что внеполосная информация управляет взаимодействием вместо гипертекста.]

+1

Это не ответ на его вопрос. API REST может поддерживать HATEOAS в течение всего дня, и тем не менее разработчикам сервера все равно нужно беспокоиться о проблемах дизайна URI. – HDave

28

Я думаю, что добавление сегмента пути/префикса - лучший ответ. Поскольку это уникальные вторичные ключи, это не то же самое, что поиск (который возвращает набор элементов), поэтому использование параметров запроса (которые не кэшируются) не похоже на лучший выбор.

Лично я планирую использовать отрезок пути префикс, ограниченную «=», как «имя =» или «электронная почта =»:

user/123456 
user/name=john.doe 
user/[email protected] 

Это функционально эквивалентно добавлению сегмента пути (например, " user/name/john.doe "), но мне кажется, что он более тесно связан с концептуальной моделью. Конечно, это незначительная деталь, так как API RESTful не должен указывать фиксированную структуру URI в любом случае.

Не используя параметры запроса также позволяет суб-ресурсы, которые будут доступны естественно:

user/name=john.doe/inbox/df87bhJXrg63 

Каркасы, как JAX-RS Явы поддерживают использование любой разделителем вы хотите:

@GET 
@Path("user/{id}") 
User getUser(@PathParam("id") UUID id); 

@GET 
@Path("user/name={name}") 
User getUserByName(@PathParam("name") String name); 

@GET 
@Path("user/email={email}") 
User getUserByEmail(@PathParam("email") String email); 
+2

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

+4

Плюс, это не очень успокоительно. что, собственно, название коллекции = john.doe? Для меня это должен быть параметр матрицы: user; name = john.doe/inbox/df87 ... http://blog.2partsmagic.com/restful-uri-design/ – Maladon

+0

@Maladon Я думаю, что вы отсутствует точка. 'name = john.doe' не должен быть коллекцией, так как' name' является уникальным идентификатором. Мы ищем ровно один объект или ошибку. 'user; name = john.doe' выглядит как поиск. Я ожидаю, что он вернет то же представление, что и 'user', которое представляет собой коллекцию. –

0

довольно старый вопрос, но У меня было то же самое и finnaly нашел решение: использовать регулярное выражение в вашем параметре пути.

Вот как я закодированы, что случай использования

@GET 
@Path("/{id : \\d+}") 
@Produces(APPLICATION_JSON) 
public Response getById(@PathParam("id") long id) { 
<<your code>> 
} 

@GET 
@Path("/{name}") 
@Produces(APPLICATION_JSON) 
public Response getByName(@PathParam("name") String name) { 
<<your code>> 
} 
+1

Что делать, если имя пользователя является числовым? Если пользователь может свободно выбирать свое имя и решает использовать только номер, ваш подход не подходит. –

+0

он терпит неудачу или нет. Вы должны сделать контроль над запросом на создание (POST) и можете отказаться от имени только числовой. – Javathought

+0

@@ POST public Response create (@Valid User user) и аннотировать вашу модель с проверкой бобов. Пример: должен начинаться с заглавной буквы, 50 символов макс. @@ Pattern (regexp = "[AZ] [a-zA-Z_0-9-] {0,49}", message = "недопустимое имя") private Имя строки; – Javathought

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