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

REST - поддержка нескольких возможных идентификаторов

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

/users/48573

И теперь он выглядит как

/users/thisisausername.

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

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

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

4b9b3361

Ответ 1

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

Лично я планирую использовать префикс сегмента пути, ограниченный "=", например "name=" или "email =":

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

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

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

user/name=john.doe/inbox/df87bhJXrg63

Рамки, такие как поддержка Java 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

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

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

/users/id/48573

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

/users/name/thisisausername

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

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

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

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

Ответ 3

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

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

@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>>
}

Ответ 4

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

/users/48573/id

/users/48573/name

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

/users/48573

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

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

/users/48573/id

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

/users/48573/name

Если вы можете получить значение по идентификатору или имени, то вы возвращаете 300 ответов и возвращаете ссылки на обе возможности клиенту:

/users/48573/id

/users/48573/name

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

Ответ 5

Ваш API не является RESTful, если это проблема. К quote Рой Филдинг:

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

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