对于我正在处理的网站,我们正在改进一种资源的网址 - 特别是从数字ID转向唯一的描述性字符串.类似的例子是从通过数字数据库ID识别用户切换到通过用户名识别它们(不是我们的具体情况,而是类似的).因此,访问用户信息的URL看起来像:
/users/48573
现在它看起来像
/users/thisisausername.
对于API的传统消费者来说,唯一的问题是我们仍然需要能够以某种方式通过数字ID获取它们.我们不需要REST URL本身来重定向(例如,/users/48573
不应该重定向到/users/thisisausername
),我们只需要一种方法来使用旧标识符获取正确的数据.该解决方案应该提供另一种方式来访问用户信息(方便地包括新标识符,用户名),或者通过ID访问用户名.一些可能的解决方案可能是
使用节点指定一些替代的识别方法,例如 /users/byid/48573
使用查询参数指定一些替代的识别方法,例如/users/48573?fetchby=id
或/users/48573?byid=true
将username-by-id视为另一种资源,例如 /identifiers/username/48573
哪些(如果有的话)最接近正确的REST?你会如何处理这个问题?
我认为添加路径段/前缀是最好的答案.由于这些是唯一的二级密钥,这与搜索(返回一组项目)不同,因此使用查询参数(未缓存)似乎不是最佳选择.
就个人而言,我打算使用由"="分隔的路径段前缀,如"name ="或"email =":
user/123456 user/name=john.doe user/email=john.doe@john.doe
这在功能上等同于添加路径段(例如"user/name/john.doe"),但我觉得它更接近于概念模型.当然,这是一个无关紧要的细节,因为RESTful API无论如何都不应该指定固定的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);
你的第一个选择可能是最好的.
按ID搜索用户:
/users/id/48573
按短名称搜索用户:
/users/name/thisisausername
如果他们省略了该路径参数,您可以始终默认使用新的短用户名格式.
我看到的另一个选项是使用如下的查询参数:
/users?id=48573 /users?name=thisisausername
我认为第一个看起来更清洁,更具可读性.