我正在寻找关于RESTful API的URI设计的一些方向。 我将有几个嵌套的链接资源,目前我的URI设计类似于这篇文章: 分层RESTful URL设计
以下示例不是我正在构建的,但我认为很好地说明了我的情况。 (假设一个节目只能属于一个网络)。
/networks [GET,POST]
/networks/{network_id} [GET,PUT]
/networks/{network_id}/shows [GET,POST]
/networks/{network_id}/shows/{show_id} [GET,PUT]
/networks/{network_id}/shows/{show_id}/episodes [GET,POST]
/networks/{network_id}/shows/{show_id}/episodes/{episode_id} [GET,PUT]
我的情况将进一步增加两个级别的协会,但所有的协会是一对多。 我正在考虑将其切换为类似的东西:
/networks [GET,POST]
/networks/{network_id} [GET,PUT]
/networks/{network_id}/shows [GET,POST]
/shows [GET]
/shows/{id} [GET,PUT]
/shows/{id}/episodes [GET,POST]
/episodes [GET]
/episodes/{id} [GET,PUT]
我的问题是:
第二个例子对我来说很好看。 URL描述了资源,并且正在使用正确的HTTP谓词。
如果有意义的话,将多个URL指向同一资源是完全正常的。 但更重要的是,确保资源包含将节目连接到网络,剧集到节目等的<link />
元素。
这里真正的问题是:你的第二个例子是否符合URI标准? URI标准规定,路径包含分层部分,查询包含非分层部分,但是afaik。 它没有说明如何在您的情况下设计URI结构。 REST统一接口约束具有HATEOAS部分,这意味着您应该在您的情况下发送回链接,指向上层和下层资源。 您应该使用元数据来注释这些链接,这些元数据可以由客户端处理,因此它将知道链接的内容。 所以在实践中,URI结构并不重要......
GET /shows/123
{
"label": "The actual show",
"_embedded": {
"episodes": [
{
"label": "The first episode of the actual show",
"_embedded": {
"associations": [
//...
]
},
"_links": {
"self": {
"label": "Link to the first episode of the actual show",
"href": "/episodes/12345"
},
"first": {
"href": "/episodes/12345"
},
"duplicate": {
"href": "/networks/3/shows/123/episodes/12345"
},
"up": {
"label": "Link to the actual show",
"href": "/shows/123"
},
"next": {
"label": "Link to the next episode of the actual show"
"href": "/episodes/12346"
},
"previous": null,
"last": {
"href": "/episodes/12350"
}
}
}//,
//...
]
},
"_links": {
"self": {
"label": "Link to the actual show",
"href": "/shows/123"
},
"duplicate": {
"href": "/networks/3/shows/123"
},
"up": {
"label": "Link to the actual network",
"href": "/networks/3"
},
"collection": {
"label": "Link to the network tree",
"href": "/networks"
},
"next": {
"label": "Link to the next show in the actual network",
"href": "/shows/124"
},
"previous": {
"label": "Link to the previous show in the actual network",
"href": "/shows/122"
}
}
}
现在,这只是具有IANA链接关系的HAL + JSON中的测试版,但您也可以使用带有RDF词汇表的JSON-LD(例如schema.org + hydra)。 这个例子只是关于层次结构(up,first,next,previous,last,collection,item等),但是你应该添加更多的元数据,例如哪个链接指向网络,哪个链接指向节目,哪个链接指向一集等等......因此,您的客户将从元数据中了解内容的内容,例如,他们可以使用链接自动导航。 这就是REST的工作原理。 所以URI结构对客户来说并不重要。 (如果您希望使响应更紧凑,也可以使用紧凑的URI和URI模板。)
URI是“可以赋予名称的任何信息”
您的问题是与域相关的问题,只有知道您使用URI命名的资源的人才能真正回答。
在尝试猜测您的域名时想到的问题是“显示”真的取决于“网络”吗?
您域中的网络是什么? 节目与网络之间的关系是什么? 这只是播放节目的人吗? 或者更多的是与生产信息有关?
我相信你的例子2更合适。
考虑到以下层次结构中存在一对多关系:
network --> shows --> episodes
我认为第二个设计没有向服务器端提供足够的信息来处理您的请求。 例如,如果您有以下数据:
Network id show_id episode_id
1 1 1
1 2 1
1 1 2
第一个详细设计将在HTTP请求中提供足够的信息来获取数据: /networks/1/shows/1/episodes/1
相反的第二种设计将具有:
/episodes/1
在第二种设计中,服务器端无法知道您的数据是指第1行还是第2行
回答你的问题:
恕我直言第二设计可能不是一个有效的REST设计为您的例子。 解决方法可能是传递查询参数
我认为设计1是自给自足的
更新:请忽略我上面的回答
另外:
/networks
/networks/{id}
/shows
/shows/{id}
/episodes
/episodes/{id}
应该有足够数量的REST URL
或换句话说,以下网址将是多余的:
/networks/{network_id} [GET,PUT]
/networks/{network_id}/shows [GET,POST]
/shows/{id}/episodes [GET,POST]
我认为我们应该尽可能简单地保持REST API URL。
例如https://www.yoursite.com/api/xml/1.0/
这里我以1.0版的XML API为例。 请记住使用API的版本以供将来更新。
您可以检查客户端请求的方法。
e.g. tag
<method>getEpisodes</method>
我认为第二个选项是Ok,但如果你想验证关系,我会考虑第一个选项。 例如,当您收到具有不同网络的剧集时,可能意味着该剧集在您的请求之前已经过修改,因此您可能需要使用422响应,对于其他服务也是如此。 有了这个,您可以确定您要工作的实体涉及其父实体。
PD:抱歉我的英文。