【问题标题】:REST - API design to get resources for current userREST - 为当前用户获取资源的 API 设计
【发布时间】:2020-06-15 21:30:26
【问题描述】:

我们有一个FitnessClassesService,可以安排健身培训课程。每个班级都有许多演员

  • 主教练解释整个锻炼过程 - 他会说话,但不一定要亲自进行锻炼。
  • 替代教练,以防主教练不在时
  • 两位培训师在课堂上通过实际练习来展示整个锻炼方式 - 一位为新手而设,一位为老前辈提供
  • 两名培训师只是在课堂上四处走动以澄清任何疑问。

当一个类被创建时,所有的actors也会被添加到它里面。培训师有一个应用程序,他们可以从中查看他们今天必须参加的课程(以任何角色)。

我通过调用POST /classes 创建类。

当培训师打开他们的应用程序时,获取所有课程的正确 REST API 是什么。这些是我考虑过的替代方案:

  • Get /classes - 从 HTTP 标头获取 userId 并使用它仅获取当前登录用户的类。但是,这对我来说似乎不是很 RESTful。
  • GET /classes/~aliceGet /classes/current - 来自 designing-uri-for-current-logged-in-user-in-rest-applications 。这只会获取由“current”用户表示的类。但是,与链接问题中“users”是资源而“current”用户代表特定资源的示例不同,我不觉得“current" 代表我的用例的资源。对我来说,“current”代表我感兴趣的所有班级。这听起来像是我必须在 classes 资源上 filter 而不是要求特定资源。
  • GET /classes?actorId=aliceGET /classes?actorId=current - 但是如果有人打电话给 GET /classes 怎么办。我是否应该验证必须始终传递一个actorId。此外,actorId 必须与登录用户的 id 匹配。是否可以根据 URI 参数进行这样的授权。
  • Get /myclasses - 使用不同的 URI。这意味着我将通过 POST /classes 创建类,但通过不同的 URI 获取类。

处理此问题的规范方法是什么。

【问题讨论】:

    标签: rest http uri api-design


    【解决方案1】:

    当培训师打开他们的应用程序时,获取所有课程的正确 REST API 是什么

    如果您想要一个 REST API,首先要仔细考虑您的 resources

    任何可以命名的信息都可以是资源:文档或图像、时间服务(例如“洛杉矶今天的天气”)、其他资源的集合、非虚拟对象(例如人)、等等。换句话说,任何可能成为作者超文本引用目标的概念都必须符合资源的定义。

    从概念上讲,“Alice 的日程”和“Bob 的日程”是资源。 “我的日程安排”也是如此,但我们当然有代词先行词的问题。

    有两种非常直接的方式来处理“我的日程安排”的经过身份验证的请求;您可以通过重定向到正确的资源来做出响应,并且您可以将正确资源的当前表示内联到您的响应中(元数据表明它来自哪里)。这些方法都很好

    (注意:RFC 7234 限制了经过身份验证的响应的 caching,这也是它“很好”的部分原因)。

    REST 不关心您的 URI 使用什么拼写(只要它符合 RFC 3986 中定义的生产规则)。所以这些都很好

    /classes/actorId=alice
    /classes?actorId=alice
    
    /classes/alice
    /classes?alice
    

    使用不同的 URI。

    还不错。

    您需要注意的一件事是 cache invalidation 与 URI 相关联;当您发布到/classes 时,它将使您在本地缓存的/classes 表示无效,但不会使您在本地缓存的/myclasses 表示无效。这意味着当您将相同的信息编码到多个资源的表示中时,这些表示不一定会同步。

    我 PUT 到 /classes/{classId} ,它会使与 /classes 关联的缓存响应无效吗?同样,如果我 POST 到 /classes,它会使与 /classes/alice 关联的缓存响应无效

    两者都没有。类似标识符所暗示的层次结构是不真实的。您通过 link relations 而非拼写来描述 URI 之间的关系,并且目前没有标准化的链接关系意味着“这些资源应该一起失效”。

    当我 PUT /classes/{classId} 时,GET /classes 的缓存不应该失效。否则 GET /classes 可能会返回 /classes/{classId}

    的陈旧表示

    就通用组件而言,/classes/{classId}/classes 完全无关。标识符是标识符,而不是“标识符和隐式链接关系”。

    描述链接之间关系的通用机制是link relation。因此,如果我们想向通用组件宣布对该资源的更改也会使该资源的缓存表示无效,我们需要类似Linked Cache Invalidation

    但是……那个草案在七年前就过期了,没有被采纳,我还没有找到替代它的替代品。

    这实质上意味着缓存失效的限制是您在设计资源模型时需要牢记的约束。如果信息 A 和信息 B 一起失效很重要,那么它们需要由相同的资源建模。

    当然,您可以在有效负载中包含缓存信息,以便自定义客户端可以知道数据无效;您在记录模式中表达链接关系,了解该模式的客户端可以选择适当的操作。如果您愿意,您甚至可以将该信息从邮件正文提升到标题。但由于没有一个标准组件知道您的新标头的含义,因此它们都忽略了它(换句话说,在我们拥有生产者和消费者都理解的合同之前,它只是噪音)。

    【讨论】:

    • 关于缓存失效的最后一条说明,如果我 PUT 到 /classes/{classId} ,它会使与/classes 关联的缓存响应失效。同样,如果我 POST 到/classes,它会使与/classes/alice 关联的缓存响应无效。您链接到的 RFC 规范说 缓存必须使有效的请求 URI 无效。在我看来,这并没有像我给出的示例那样说明相关的 URI。
    • 不,您无法通过设计巧妙的标识符拼写来控制缓存行为。
    • 对不起,我不太明白。当我PUT /classes/{classId} 时,GET /classes 的缓存不应该失效。否则GET /classes 可能会返回/classes/{classId} 的陈旧表示
    猜你喜欢
    • 2021-09-02
    • 2015-03-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    • 2015-08-28
    • 2020-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多