我正在开发我的第一个Hypermedia API。我认为我对事物有很好的把握,但在记录API时,我开始质疑我对整个概念的理解。
问题的核心归结为文档,但可能是我没有正确理解一个或多个方面。如果是这样,请告诉我: - )
假设我的API中有一个或多或少的通用链接关系(https://example.com/rels/accounts
)来链接相关帐户。确切的含义可以在上下文中改变,对吗?
我该如何记录这种关系?只是说这是一个帐户集合的链接似乎还不够。然而,这正是RFC5988所做的,只是描述了链接本身的含义。所以这可能是要走的路。
实际状态转换会使问题变得更糟。我们在此处使用https://example.com/rels/create-account
作为示例。如果文档只是说“这是您创建新帐户的位置”,那么它不会对我使用该链接创建资源所做的事情做出任何陈述。文档在哪里说明了一些内容:
您可以将multi multipart / form-data或application / json POST到此端点,该端点至少包含以下字段[...]
关系本身似乎不是正确的地方。特别是当您考虑到该URL的有效负载也可能在上下文中更改时。在我们的示例中,在帐户组上设置该关系会强制要求省略 accountGroup 字段,因为该值是由上下文提供的。
据我了解,我可以(也可能应该)为我的API中的每个资源创建一个配置文件,记录资源本身。这将包括其属性和可能发生的链接。那会是我指定链接意味着什么的地方吗?
坚持我之前的示例,我是否会为个人资料https://example.com/profiles/account-group
记录关系https://example.com/rels/accounts
的链接是否链接到该群组中的一组帐户?
这对我来说很有意义,但是当我们进入实际状态转换时,事情似乎变得混乱。
假设客户端从帐户组导航到帐户集合。资源本身与包含所有全局帐户的资源实际上没有区别。它会有分页链接和帐户资源本身的链接。
如果该帐户收集资源有一个关系类型https://example.com/rel/create-account
的链接,我会遇到很大麻烦,对吧?因为这是仅包含特定组帐户的帐户集合的信息未在配置文件中编码
https://example.com/profiles/account-collection
,因此不能包含客户在发布到该资源时必须省略 accountGroup 属性的信息。
https://example.com/profiles/global-accounts
和https://example.com/profiles/account-group-accounts
。我越是想到它,我必须要么错过一个关键部分,要么就是可以通过多种方式解决的问题。因此,我知道这个问题可能没有100%正确答案。但也许有人可以启发我,以便我可以自己做出权衡? :)
答案 0 :(得分:1)
让我们一次一个点:
<强> 1。基于上下文的链接关系含义
将您的问题重新表述为代码上下文:如何记录&#34; getAccounts()&#34;方法在Billboard和AccountGroup类中意味着什么不同?
显而易见的答案是,您通常不会记录该方法,但是您可以记录这些类,并在其中记录方法。您所指的RFC试图定义某种意义上的通用关系,或者每次都应该意味着相同的关系。您可能会重复使用其中的一些,但您仍需记录该方法及其在课堂中的含义。
类等于您的媒体类型。所以我建议你记录你的媒体类型。
<强> 2。链接和表单,如何定义POST的内容
如果您记录媒体类型,则可以在其中定义您喜欢的内容,包括如何使用其链接。但是,我建议不要定义POST的媒体类型,但要将其设置为Content-Negotiation。
客户端知道它必须POST一个帐户,它将使用它认为适合此任务的某些媒体类型。然后,服务器会告诉客户端该格式是否可接受,它还可以提供可接受的媒体类型列表作为回报。
第3。记录配置文件
如果“个人档案”是指媒体类型,那么是的,您应该记录它们。实际上你应该只记录媒体类型。
<强> 4。状态转换,基于状态的表示修改
由于帐户组无论如何都是资源,客户端实际上不应该提供它,它应该是&#34; state&#34;新帐户所属的组。
换句话说,客户端获得一个已具有当前帐户组上下文的链接。客户端必须发布一个通用帐户,但服务器知道它应属于当前状态的组(例如,它是URI的一部分)
所以不,客户不应该知道它必须省略一些参数。
<强> 5。问题强>
是的,关系不应该定义如何与资源进行交互。媒体类型实际上可以做到这一点(比如定义它的表格必须是POST等),但通常情况下它不是必需的。
是的,客户不仅会发现可用的转换(链接),还会发现可用的方法。方法(GET,POST,PUT)总是意味着相同的事情,并且它们没有在媒体类型中描述,因为媒体类型只描述表示,而不是资源。服务器通常在响应中提交所有支持的方法,或者明确地响应OPTIONS。
我仍然不知道你的意思&#34;简介&#34;。如果您的意思是关系配置文件,就像链接定义中的某些数据一样,则为no。上下文/状态在URI中传播。您可以使用URI来&#34;保存&#34;例如,客户端正在一个帐户组内移动。
不,你不应该为链接关系添加语义。 Media-Type将语义添加到链接。
HTH
答案 1 :(得分:1)
我会尝试比罗伯特的答案更简洁地回答,我认为这会让人感到困惑。
假设我的API中有一个或多或少的通用链接关系(
https://example.com/rels/accounts
)来链接相关帐户。确切的含义可以在上下文中改变,对吗?
否。链接关系的含义是静态的。您的索引(列表列表)页面上的“帐户列表”关系特定于您的应用程序。在您的另一个示例帐户组中,您已经在“集合”资源中,该集合的成员具有链接关系“item”(请参阅IANA link relations列表)。
实际状态转换会使问题变得更糟。我们在此处使用
https://example.com/rels/create-account
作为示例。如果文档只是说“这是您创建新帐户的地方”
我会在“帐户列表”页面中添加“创建表单”链接(另一个标准的IANA链接关系)。然后你的客户会去:开始 - &gt; list-of-Xes - &gt;创建形式 - &gt;提交。不存在“create-an-X”或“create-a-Y”链接关系。您可能不允许客户端创建新的集合类型。这使得为客户端导航API更长,但减少了他们需要知道的内容(API广度)。
[profile]会指定链接的含义吗?
如果您将链接关系设为通用除了描述每个模型类之外的链接关系,则不必在每个模型类的基础上在配置文件中记录这些关系。
如果该帐户收集资源有一个关系类型
https://example.com/rel/create-account
的链接,我会遇到很大的麻烦,对吗?
是的,所以不要这样做!您在那里描述的是将现有资源链接到collection
(根据IANA的定义)。我建议您支持客户能够这样做:
LINK http://site/account-collections/some-collection HTTP/1.1
Link: <http://site/accounts/some-account-id>; rel=item
Authorization: Token abc123
这个简单(完整!)的HTTP请求具有将包含现有帐户URI的“item”链接添加到要添加到其中的集合的语义。它不会创建新帐户。 LINK method仍处于草案状态,但自HTTP 1.1(1997)以来一直以某种形式存在。
罗伯特写道:您实际上应仅记录媒体类型。
我不同意。您也应记录链接关系,但如果可以使用通用链接关系,请尽量不创建它们。