rest - REST - 为当前用户获取资源的 API 设计
问题描述
我们有一个FitnessClassesService
允许安排健身培训课程。每个班级都有许多演员:
- 解释整个锻炼的主要教练- 他会说话,但不一定自己做锻炼。
- 在主教练不在的情况下替代教练
- 两位教练通过在课堂上实际练习来展示整个锻炼 - 一位针对新手,一位针对老前辈
- 两名培训师只是在课堂上四处走动以澄清任何疑问。
当一个类被创建时,所有的actors也会被添加到它里面。培训师有一个应用程序,他们可以从中查看他们今天必须参加的课程(以任何角色)。
我通过调用创建类POST /classes
。
当他们打开他们的应用程序时,为培训师获取所有课程的正确 REST API 是什么。这些是我考虑的替代方案:
Get /classes
- 从 HTTP 标头中获取 userId,并使用它仅获取当前登录用户的类。但是,这对我来说似乎不是很 RESTful。GET /classes/~alice
或Get /classes/current
- 从设计 uri-for-current-logged-in-user-in-rest-applications。这只会获得由“当前”用户表示的类。但是,与链接问题中“用户”是资源而“当前”用户代表特定资源的示例不同,我不觉得“当前”代表我的用例的资源。对我来说, “当前”代表我感兴趣的所有班级。这听起来像是我必须filter
使用classes
资源而不是要求特定资源。GET /classes?actorId=alice
或GET /classes?actorId=current
- 但如果有人打电话怎么办GET /classes
。我是否应该验证必须始终传递一个actorId。此外,actorId 必须与登录用户的 id 匹配。是否可以根据 URI 参数进行此类授权。Get /myclasses
- 使用不同的 URI。这意味着我将POST /classes
通过不同的 URI 创建类但获取类。
处理此问题的规范方法是什么。
解决方案
当他们打开他们的应用程序时,为培训师获取所有课程的正确 REST API 是什么
如果您想要一个 REST API,一个早期的步骤是仔细考虑您的资源。
任何可以命名的信息都可以是资源:文档或图像、时间服务(例如“洛杉矶今天的天气”)、其他资源的集合、非虚拟对象(例如人)等等. 换句话说,任何可能成为作者超文本参考目标的概念都必须符合资源的定义。
从概念上讲,“Alice 的日程”和“Bob 的日程”是资源。“我的日程安排”也是如此,但当然我们有一个代词先行词问题。
有两种非常直接的方式来处理“我的日程安排”的经过身份验证的请求;您可以通过重定向到正确的资源来做出响应,并且您可以将正确资源的当前表示内联到您的响应中(元数据表明它来自哪里)。这些方法都很好。
(注意:RFC 7234 限制了已验证响应的缓存,这也是它“很好”的部分原因)。
REST 不关心您对 URI 使用什么拼写(只要它符合 RFC 3986 中定义的生产规则)。所以所有这些都很好
/classes/actorId=alice
/classes?actorId=alice
/classes/alice
/classes?alice
使用不同的 URI。
还好。
您需要注意的一件事是缓存失效与 URI 相关联。当您发布到 时/classes
,它将使您的本地缓存表示无效,但不会使您的本地缓存表示/classes
无效/myclasses
。这意味着当您将相同的信息编码到多个资源的表示中时,这些表示不一定会同步。
我 PUT 到 /classes/{classId} ,它会使与 /classes 关联的缓存响应无效。同样,如果我 POST 到 /classes,它会使与 /classes/alice 关联的缓存响应无效吗
对两者都没有。类似标识符所暗示的层次结构是不真实的。您通过链接关系而不是拼写来描述 URI 之间的关系,并且目前没有标准化的链接关系意味着“这些资源应该一起失效”。
当我 PUT /classes/{classId} 时,GET /classes 的缓存不应该失效。否则 GET /classes 可能会返回 /classes/{classId} 的陈旧表示
就通用组件而言,/classes/{classId}
与/classes
. 标识符是标识符,而不是“标识符和隐式链接关系”。
用于描述链接之间关系的通用机制是链接关系。因此,如果我们想向通用组件宣布对该资源的更改也会使该资源的缓存表示无效,我们将需要类似Linked Cache Invalidation的东西。
但是……那个草案在七年前就过期了,没有被采纳,我还没有找到替代它的方法。
这实质上意味着缓存失效的限制是您在设计资源模型时需要牢记的约束。如果信息 A 和信息 B 一起失效很重要,那么它们需要由相同的资源建模。
当然,你可以在你的payload中包含缓存信息,这样自定义客户端就可以知道数据是无效的;您在记录模式中表达链接关系,了解该模式的客户端可以选择适当的操作。如果您愿意,您甚至可以将该信息从邮件正文提升到标题。但是由于没有一个标准组件知道您的新标头的含义,因此它们都忽略了它(换句话说,在我们拥有生产者和消费者都理解的合同之前,它只是噪音)。
推荐阅读
- python - ValueError:序列太大;不能大于 32
- python - 使用 azureml-sdk 时出现 numpy 错误
- google-sheets - 在 Google 表格中使用多列数据进行匹配并返回值
- r - 将一列中的文本拆分为每行的多列
- laravel - 如何将一个类别重定向到子类别?
- oracle - 由于会话状态值导致的 Oracle Apex 性能问题
- hadoop - 如何调试 map-reduce 失败的地方?
- javascript - 如何遍历多个相似元素并依次更改每个元素的属性?
- optimization - 优化 Pywinauto
- python - 如何在 Python 中切换嵌套字典的值和键?