我正在为RESTful API设计自定义媒体类型,并研究了一些“标准”链接关系的类型和语义含义,以便为我的设计提供一些引导。
为了演示这个问题,让我说我有一个资源,我可以执行标准的读取,更改,删除方法,并分别使用GET,PUT和DELETE的HTTP惯用法来实现这些方法。
我可以合理地(重新)使用IANA link registry中定义的“编辑”链接关系(来自RFC5023),其中指出:
“...”edit“的值指定href属性的值 是可编辑成员条目的IRI。当出现在 atom:entry,href IRI可用于检索,更新和删除 该条目所代表的资源......“
通过这种方式,用户代理可以理解具有“编辑”关系的链接将允许资源为GET,PUT和DELETEd。
然而,这里存在的问题是,如果编辑资源状态使得资源现在仅支持GET和DELETE操作,则“编辑”关系不再精确。
为了保持我需要的精度i)选项A:指定支持GET&的另一个(复合)链接关系。仅删除,或ii)选项B:为每个可能的状态转移指定单独的链接,并使用适当的链接指示允许的状态转移。后一种方法提供精确但似乎过于冗长。
或者,(选项C)我可以保持“编辑”关系并接受缺乏精确性,即链接将传达GET,PUT,DELETE语义,但尝试PUT的用户代理将遇到HTTP错误'405 - 方法不允许'。但是,我对这种方法不满意,因为它意味着客户端不支持状态转换。
总之,问题是平衡链接关系的一般性和精确度最明智的方法是什么?
答案 0 :(得分:2)
经过一番认真调查后,我得出结论,我正试图解决错误的问题。而不是关注链接关系定义中的HTTP动词的粒度,更精确的问题是“HTTP惯用语(动词)是否应该混合到链接关系中?”。
我曾使用AtomPub作为如何进行链接关系(对于REST)的参考,结果发现这是一个错误。在AtomPub mail archive Roy Fielding建议(以REST术语)“编辑”的方法是错误的,并得出结论认为没有必要。该论点表明还有其他(HTTP)机制来传达这些属性,因此它们在'rel'属性中没有位置。
其他机制在邮件存档中没有明确说明,但我怀疑它们包含以下选项:
有趣的是,Roy认为'Allow' header是“一种超文本形式”。
总之,我自己的问题的答案是:
“不要将HTTP操作混淆为'rel'”
的含义
和
“使用(提供的)HTTP机制来确定允许的资源操作”
编辑:我应该补充一点,POST的一些特殊用途是作为数据接收器,这些规则需要稍微弯曲,但是它们是一个特例。
答案 1 :(得分:1)
WRML规范采用一种方法,其中每个“链接”对象都可以具有rel属性。
GET /dogs/1
{
"links" : {
"self" : {
"href" : "http://api.example.com/dogs/1
"rel" : "http://api.example.com/relations/self"
}
}
}
然后客户端可以关注rel url
GET /relations/self
{
"name" : "self"
"description" : " A reference back to the same object you are currently interacting with"
"method" : "GET"
}
规范建议每个rel应该指定1个方法。这样做的好处是能够明确地向客户说明他们应该做什么,并限制所需的带外知识量。我个人就此反复讨论,因为我认为某些“rel”提供多种HTTP方法是有一定价值的。想象一下狗的主人的链接
GET /dogs/1
{
"links" : {
"self" : {
"href" : "http://api.example.com/dogs/1
"rel" : "http://api.example.com/relations/self"
}
"owner" : {
"href" : "http://api.example.com/owner/1
"rel" : "http://api.example.com/relations/owner"
}
}
}
让“所有者”暗示GET和PUT会很好,因为这些都是有效的行动。与此相反的是,在进行更新之前,您应该总是需要进行GET,因此在检索资源之前提供该信息的价值是不好的形式。
所以我想这就是说我会投票给选项B.
答案 2 :(得分:0)
另一种选择是保留“编辑”关系,并允许想要知道他们当前可以在资源上执行什么的消费者使用OPTIONS HTTP方法发出请求,并且服务器可以返回带有{的响应{3}}标头指示资源允许的方法,因为它是当前状态。
如果没有额外的请求,它不会为您提供PUT操作的可用性,但它相当“干净”,并允许您使用标准关系和HTTP机制。