我有一个处理网络上视频服务器的REST服务。
每个视频服务器都可以通过多种方式识别:通过序列号, 按名称或机器编号。
用于返回网络上可用的所有服务器的集合 非常简单:我已经定义了以下路线:
[Route("/servers", "GET")]
以及以下请求类:
public class ServerCollection : IReturn<List<ServerDto>>
{
...
}
现在,我想从我的收藏中返回一个特定的服务器,进行识别 它可以是序列号,机器名称,也可以是机器编号。
为此,我定义了以下路线:
[Route("/servers/{SerialNumber}", "GET")]
[Route("/servers/machinenumbers/{MachineNumber}", "GET")]
[Route("/servers/machinenames/{MachineName}", "GET")]
以及以下请求类:
public class Server : IReturn<ServerDto>
{
public uint SerialNumber { get; set; }
public uint MachineNumber { get; set; }
public string MachineName { get; set; }
}
所以,我可以通过以下方式访问我的服务器集合:
GET /servers
使用以下任一项获取特定服务器:
GET /servers/3
GET /servers/machinenumbers/42
GET /servers/machinenames/supercalifragilisticexpialidocious
这是正确的方法吗?我觉得这不是很好 REST风格。我应该将此视为我的收藏中的搜索,而不是使用“人工” 资源?
答案 0 :(得分:2)
我会以一种始终唯一的方式表示服务(序列号可能是正确的)。
对于查询,我会执行类似/servers/?name=[name]
或/server/?id=[id]
或/servers/[serial]
的操作(如果您想直接使用序列号)。在请求名称或ID时,您应该将请求中的网址更改为servers/[serial]
以保持网址唯一。
答案 1 :(得分:2)
我相信这是ServiceStack方式。只需使两个uint
字段都可以为空,这样在服务实现中你就可以确定搜索的参数是什么。
答案 2 :(得分:1)
没关系,只要你将两个URI重定向(3xx)到另一个,而不是在所有三个都返回相同的表示(2xx)。否则,您将有一段时间让副本在缓存中保持同步。在您的情况下,将machinenumbers和machinenames资源重定向到servers / {id}资源似乎是合乎逻辑的。
如果有的话,它是使用与REST对立的k = v参数的通用搜索。请记住,URI标识资源,而查询字符串是URI的一部分:不同的查询字符串标识不同的资源。由于表单样式查询字符串中的术语集通常较大(为了方便起见),并且术语可以按任何顺序出现,这会导致潜在资源的爆炸(如果您不打算依赖于缓存效率,那么你有很多其他的选择,但那不是REST)。