我认为您应该考虑创建SpecialToken
一个资源,并允许 api 的使用者使用POST
它来检索一个新实例。不知何故,您需要将资源链接User
到SpecialToken
资源。请记住,REST 的中心原则之一是您不应该依赖带外信息,因此如果您想忠于这一点,您将需要调查使用链接的可能性。
首先,让我们看看你有什么:
要求:
GET /User/1
Accept: application/json
回复:
200 OK
Content-Type: application/json
{
"Id": 1,
"Email": "myemail@gmail.com",
"SpecialToken": "12345689"
}
尽管此响应确实包含SpecialToken
对象中的属性,但Content-Type
对于application/json
未编程为理解此特定对象结构的客户端而言,它实际上并没有任何意义。只理解 JSON 的客户端会像其他任何对象一样将其视为对象。让我们暂时忽略它。假设我们的想法是为该SpecialToken
领域使用不同的资源;它可能看起来像这样:
要求:
GET /User/1/SpecialToken
Accept: application/json
回复:
200 OK
Content-Type: application/json
{
"SpecialToken": "12345689"
}
因为我们做了一个GET
,所以理想情况下进行这个调用不应该修改资源。然而,该POST
方法不遵循那些相同的语义。事实上,很可能POST
向该资源发出消息可能会返回不同的正文。因此,让我们考虑以下内容:
要求:
POST /User/1/SpecialToken
Accept: application/json
回复:
200 OK
Content-Type: application/json
{
"SpecialToken": "98654321"
}
请注意POST
消息如何不包含正文。这可能看起来不合常规,但 HTTP 规范并没有禁止这样做,事实上 W3C TAG 说没关系:
请注意,即使不在 HTTP 消息正文中提供数据,也可以使用 POST。在这种情况下,资源是 URI 可寻址的,但 POST 方法向客户端指示交互不安全或可能有副作用。
听起来对我来说是正确的。过去,我听说一些服务器在POST
没有正文的消息方面存在问题,但我个人对此没有任何问题。只要确保Content-Length
标题设置正确,你就应该是金色的。
因此,考虑到这一点,这似乎是一种完全有效的方式(根据 REST)来执行您的建议。但是,还记得之前我提到过关于 JSON 实际上没有任何应用程序级语义的内容吗?好吧,这意味着为了让您的客户端真正发送 aPOST
以获取新SpecialToken
资源,它需要知道该资源的 URL,或者至少知道如何制作这样的 URL。这被认为是一种不好的做法,因为它将客户端与服务器联系在一起。让我们来说明一下。
鉴于以下要求:
POST /User/1/SpecialToken
Accept: application/json
如果服务器不再识别 URL /User/1/SpecialToken
,它可能会返回 404 或其他适当的错误消息,并且您的客户端现在已损坏。要修复它,您需要更改负责的代码。这意味着您的客户端和服务器不能彼此独立发展,并且您已经引入了耦合。但是,如果您的客户端 HTTP 例程允许您检查标头,则修复此问题相对容易。在这种情况下,您可以引入指向您的消息的链接。让我们回到我们的第一个资源:
要求:
GET /User/1
Accept: application/json
回复:
200 OK
Content-Type: application/json
Link: </User/1/SpecialToken>; rel=token
{
"Id": 1,
"Email": "myemail@gmail.com",
"SpecialToken": "12345689"
}
现在在响应中,标题中指定了一个链接。这个小小的添加意味着您的客户不再需要知道如何获取SpecialToken
资源,它只需点击链接即可。虽然这并不能解决所有耦合问题(例如,token
不是注册的链接关系),但它确实有很长的路要走。您的服务器现在可以随意更改SpecialToken
URL,您的客户端无需更改即可工作。
这是 HATEOAS 的一个小例子,是 Hypermedia As The Engine Of Application State 的缩写,本质上意味着您的应用程序会发现如何做事,而不是预先知道它们。首字母缩略词部门的某个人确实因此而被解雇。为了满足您对这个主题的兴趣,Jon Moore 有一个非常酷的演讲,展示了一个广泛使用超媒体的 API。另一个很好的超媒体介绍是Steve Klabnik 的著作。这应该让你开始。
希望这可以帮助!