更新/创建分层资源REST

Ame*_*osa 20 rest

我正在努力REST API,我正在努力了解如何处理分层资源.

背景

让我们从一个简单的例子开始.在我的API中,我有用户,用户个人资料评论.

  • 用户必须关联用户配置文件(用户配置文件仅对应一个用户)
  • 用户可能关联了评论(评论仅对应一个用户)

用户的资源表示应该是:

User: {
   "u1": "u1value", // User's attributes
   "u2": "u2value",
   ...
   "links": [{
       "rel": "profile",
       "href": "http://..." // URI of the profile resource
   }, {
       "rel": "review",
       "href": "http://..." // URI of the review resource
   }]
}
Run Code Online (Sandbox Code Playgroud)

用户配置文件资源表示应为:

UserProfile: {
   "p1": "p1value", // Profile attributes
   "p2": "p2value",
   ...
   "links": [{
       "rel": "owner",
       "href": "http://..." // URI of the user resource
   }]
}
Run Code Online (Sandbox Code Playgroud)

审核资源表示应该是:

Review: {
   "r1": "r1value", // Review attributes
   "r2": "r2value",
   ...
   "links": [{
       "rel": "owner",
       "href": "http://..." // URI of the user resource
   }]
}
Run Code Online (Sandbox Code Playgroud)

资源URI可以是:

  • http://api.example.com/users/{userid}:访问用户资源
  • http://api.example.com/users/{userid}/profile:访问用户的个人资料资源
  • http://api.example.com/users/{userid}/review:访问用户的审阅资源

资源创建:创建用户的正确方法是什么?

现在我想创建一个新用户:

  1. POST http://api.example.com/users {"u1": "bar", "u2": "foo"} 然后我找回新的userid = 42
  2. POST http://api.example.com/users/42/profile {"p1": "baz", "p2": "asd"}
  3. PUT http://api.example.com/users {"u1": "bar", "u2": "foo", links: [{"rel": "profile", "href": "http://api.example.com/users/42/profile"]}

我的担忧:

  • 如果某事在1到2或2和3之间断裂怎么办?
  • 在3)中,服务器是否应自动更新http://api.example.com/users/42/profile中的链接,以指向正确的所有者?
  • 更新链接字段是创建关系的正确方式吗?或者我应该跳过步骤3)并让系统根据URI约定猜测关系?(我在几本书上看到URI应该被认为是不透明的.)

And*_*ock 16

您的问题得到妥善解决,问题清单正确无误.如果我建议,你的方法看起来非常像你正在使用关系数据库方法并且正在执行INSERT,从用于下一个INSERT的序列中检索PK,依此类推.

让服务器保持参照完整性

作为观察,即使遵循原始方案,也完全省略步骤3.links检索用户文档时,可见的URI 应由服务器根据配置文件记录的存在生成.

例如,如果使用关系后端,则从USERS中选择以获取用户记录.接下来,从PROFILES中选择.如果有记录,则修改返回数据结构以包含引用.

POST整个文件

解决您提出的其他问题的常用方法是允许将整个文档发布到用户URL(如NoSQL数据库,如MongoDB).这里的文档是用户配置文件:

{ 
   "u1": "bar",
   "u2": "foo",
   "profile": {  
                 "p1": "baz",
                 "p2": "asd"
              }
}
Run Code Online (Sandbox Code Playgroud)

在这种方法中,在服务器上的端点接收到一个嵌套结构(文件),并执行将插件插入用户,检索PK,然后执行INSERT成使用该PK曲线.在服务器端执行此操作可以解决几个问题:

  1. 交易可以是原子的
  2. 客户端和服务器之间只有一个网络交换
  3. 服务器执行繁重的工作并且可以验证整个事务(例如,如果配置文件无效,则不会创建用户)
  4. 不需要第3步.

请注意,除了上面详述的API 之外,您还可以使用此方法- 您仍然希望能够直接访问用户的个人资料.

GET - 客户端可以指定字段

与来自知名公司的API进行比较是有趣的.以LinkedIn为例.在他们的开发人员API中,用户的默认GET只返回用户的名称,标题和URI.

但是,如果请求指定了其他字段,则可以获取嵌套数据,例如http://developer中的第二个示例.linkedin.com/documents/understanding- field- selectors返回用户名和列表公司名称他们举行了.您可以为"个人档案和评论"实施类似的方案.

用于更新文档属性的PATCH

通过插入和查询,可能值得考虑如何更新(PATCH)数据.覆盖一个字段是显而易见的,所以你可以,例如PATCH到http://api.example.com/users/42以下内容:

{ 
   "u1": null,
   "u2": "new-foo",
   "profile": {  "p1": "new-baz"}
}
Run Code Online (Sandbox Code Playgroud)

这将取消设置u1,设置u2new-foo和更新配置文件的p1new-baz.请注意,如果缺少某个字段(p2),则不会修改该字段.如本答案所述,PATCH优于较旧的PUT .

如果您只需要更新配置文件,请将新的配置文件记录直接打印到http://api.example.com/users/42/profile

DELETE应该级联

最后,删除可以使用DELETE方法指向您要删除的资源 - 无论是用户,个人资料还是审阅​​.实施级联删除,以便删除用户删除他/她的个人资料和评论.