在自定义媒体类型中链接关系粒度与精度?

时间:2012-02-27 14:21:41

标签: api rest hateoas hypermedia

我正在为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 - 方法不允许'。但是,我对这种方法不满意,因为它意味着客户端不支持状态转换。

总之,问题是平衡链接关系的一般性和精确度最明智的方法是什么?

3 个答案:

答案 0 :(得分:2)

经过一番认真调查后,我得出结论,我正试图解决错误的问题。而不是关注链接关系定义中的HTTP动词的粒度,更精确的问题是“HTTP惯用语(动词)是否应该混合到链接关系中?”。

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

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

  1. 让用户代理尝试检查响应(2xx或4xx)或
  2. 使用OPTIONS向资源询问允许的操作,或
  3. 在成功的GET请求中包含“允许”标题 允许对用户代理的资源操作。
  4. 有趣的是,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机制。