5

我正在为 RESTful API 设计自定义媒体类型,并研究了一些“标准”链接关系的类型和语义含义,以便为我的设计提供一些指导。

为了演示这个问题,假设我有一个可以执行标准读取、更改、删​​除方法的资源,并且我分别使用 GET、PUT 和 DELETE 的 HTTP 习惯用法来实现这些方法。

我可以合理地(重新)使用RFC5023中定义的“编辑”链接关系(来自IANA 链接注册表),其中规定:

"..."edit" 的值指定 href 属性的值是可编辑成员条目的 IRI。当出现在 atom:entry 中时,href IRI 可用于检索、更新和删除资源由那个条目代表......”

这样,用户代理可以理解具有“编辑”关系的链接将允许对资源进行 GET、PUT 和 DELETE。

然而,问题就在这里,如果资源状态被编辑使得资源现在只支持 GET 和 DELETE 操作,“编辑”关系就不再精确。

为了保持精度,我需要 i) 选项 A:指定另一个(复合)链接关系,仅支持 GET & DELETE,或 ii) 选项 B:为每个可能的状态转移指定单独的链接并使用适当的链接来指示允许的状态转移。后一种方法提供了精确性,但似乎过于冗长。

或者,(选项 C)我可以保留“编辑”关系并接受缺乏精度,即链接将传达 GET、PUT、DELETE 语义,但尝试 PUT 的用户代理将遇到 HTTP 错误' 405 - 不允许的方法'。但是,我对这种方法也不满意,因为它向客户端暗示了不支持的状态转换。

总而言之,问题是平衡链接关系通用性和精度的最明智的方法是什么?

4

3 回答 3

2

经过一些认真的调查后,我得出结论,我正在尝试解决错误的问题。与其关心链接关系定义中 HTTP 动词的粒度,一个更精细的问题是“应该将 HTTP 习语(动词)合并到链接关系中吗?”。

我曾使用 AtomPub 作为如何进行链接关系(用于 REST)的参考,结果证明这是一个错误。在AtomPub 邮件存档中,Roy Fielding 建议(在 REST 术语中)“编辑”方法是错误的,并得出结论认为这是不必要的。该论点表明还有其他(HTTP)机制来传达此类属性,因此它们在“rel”属性中没有位置。

邮件存档中没有明确说明其他机制,但我怀疑它们包括以下选项:

  1. 让用户代理尝试检查响应(2xx 或 4xx),或者
  2. 使用 OPTIONS 向资源询问允许的操作,或
  3. 在成功的 GET 请求中包含一个“允许”标头,以将允许的资源操作传递给用户代理。

有趣的是,Roy 认为“允许”标题是“一种超文本形式”。

总之,我自己的问题的答案是:

不要将 HTTP 操作混为 'rel' 的含义

使用(提供的)HTTP 机制来确定允许的资源操作

编辑:我应该补充一点,POST 作为数据接收器有一些特殊用途,这些规则需要稍微弯曲,但它们是一种特殊情况。

于 2012-05-15T20:06:26.213 回答
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。

于 2012-02-28T15:02:55.417 回答
0

另一种选择是离开“编辑”关系,并允许想知道他们当前可以在资源上执行什么的消费者使用 OPTIONS HTTP 方法发出请求,服务器可以返回带有Allow标头的响应以指示给定当前状态的资源上允许的方法。

它不会在没有额外请求的情况下为您提供 PUT 操作的可用性,但它相当“干净”并允许您使用标准关系和 HTTP 机制。

于 2012-02-28T02:23:56.547 回答