【问题标题】:Does my API design violate RESTful principles?我的 API 设计是否违反了 RESTful 原则?
【发布时间】:2010-03-28 05:29:31
【问题描述】:

我目前(我正在尝试)为社交网络设计一个 RESTful API。但我不确定我目前的方法是否仍然符合 RESTful 原则。如果一些聪明的头脑能给我一些建议,我会很高兴。

假设以下 URI 表示用户帐户的名称字段:

people/{UserID}/profile/fields/name

但是有近百种可能的字段。所以我希望客户创建自己的字段视图或使用预定义的视图。假设以下 URI 表示一个预定义的字段视图,其中包括字段“name”、“age”、“gender”:

utils/views/field-views/myFieldView

由于字段视图是一种更高层次的逻辑,我不想将字段视图的支持混入“people/{UserID}/profile/fields”资源中。相反,我想做以下事情:

utils/views/field-views/myFieldView/{UserID}


另一个例子


假设我们要执行一些数量运算(希望这是正确的英文名称)。我们有以下 URI,而每个 URI 都指向一个人列表——他们的朋友:

GET people/exampleUID-1/relationships/friends
GET people/exampleUID-2/relationships/friends

现在我们想知道他们的哪些朋友也是我的朋友。所以我们这样做:

GET people/myUID/relationships/intersections/{Value-1};{Value-2}

而“{Value-1/2}”是“people/exampleUID-1/friends”和“people/exampleUID-2/friends”的 url 编码值。然后我们得到所有三个人的朋友的代表。

虽然 Leonard Richardson 和 Sam Ruby 在他们的“RESTful Web Services”一书中指出 RESTful 设计在某种程度上类似于“极端面向对象”的方法,但我认为我的方法是面向对象的,因此符合 RESTful 原则。还是我错了?

如果不这样做:在谨慎使用此类“面向对象”方法并避免基于查询的 REST-RPC 混合时,通常是否鼓励使用?

提前感谢您的反馈,

宠物

【问题讨论】:

    标签: api architecture rest


    【解决方案1】:

    我从未使用过 REST,但我假设在 '''/people/{UserId}/profile''' 处获取配置文件资源会生成 XML 或 JSON 或其他格式的文档,即包括所有字段。在客户端,我会忽略我不感兴趣的字段。这不是比必须(a)在服务器上配置个性化视图或(b)发出大量请求来获取每个字段更好吗?

    【讨论】:

    • 同意。考虑将用户配置文件作为粒度单位,而不是名称等单个字段。
    • 另外,考虑为每个资源存储一个版本或时间戳字段,以便检测和处理并发更新尝试。
    • Richard, C. Dragon:感谢您的反馈,但是当我将用户配置文件作为粒度单位时,每次我想消费/更新特定字段时都会产生巨大的开销。大约有。 50 种可能的字段类型。我认为,平均遍历一个 700 人的列表并且每次都必须丢弃这个开销并不是很有效。这就是为什么我要引入自定义视图——以避免不必要的过载。
    • @Richard, C.Dragon:我同意 - “/people/{UserID}/profile” 绝对应该为客户提供所有字段。然而,在处理更大的资源时,拥有一个额外的机制可能会很有用——从技术上讲,这与使用分页来将视图限制在资源的一个子集上的情况类似。 @C。 Dragon 76:尽管时间戳使设计复杂化,但我不得不同意。但是我会存储它们以使 API 及其客户端能够正确使用缓存(HEAD 方法)。
    【解决方案2】:

    嗨,peta,
    我自己仍在阅读RESTful Web Services,但我建议采用与提议的方法略有不同的方法。

    关于您帖子的第一部分:

    utils/views/field-views/myFieldView/{UserID}
    

    我不认为这是 RESTful,因为 utils 不是资源。定义自定义视图是可以的,但是这些视图应该是(恕我直言)API URI 方案的自然部分。要将上述内容合并到您的第一个 URI 示例中,我将提出以下示例之一,而不是为其创建特殊视图:

    people/{UserID}/profile/fields/name,age,gender/
    people/{UserID}/profile/?fields=name,age,gender
    

    后一个示例将fields 视为算法的输入值。这可能是比在 URI 中包含 fields 更好的方法,因为它本身不是资源 - 它只是对 people/{UserID}/profile/ 的现有视图施加限制。从技术上讲,它与分页非常相似,默认情况下您会限制视图并允许客户端使用?page=1?page=2 等来浏览资源。

    关于您帖子的第二部分:
    这是一个更难破解的。

    第一: 在 URI 中包含 intersection 会稍微破坏您的 URI 方案。它本身不是一种资源,而且它与friends 位于同一级别,而它更适合低于一个级别或作为您的算法的输入值,即

    GET people/{UserID}/relationships/friends/intersections/{Value-1};{Value-2}
    GET people/{UserID}/relationships/friends/?intersections={Value-1};{Value-2}
    

    我个人再次倾向于后者,因为与第一种情况类似,您只是在限制 people/{UserID}/relationships/friends/ 的现有视图

    其次,关于:

    而“{Value-1/2}”是网址 的编码值 “人/exampleUID-1/朋友”和 “人/exampleUID-2/朋友”

    如果您的意思是 {Value-1/2} 包含提到的 GET 请求的整个编码响应,那么我会避免这种情况 - 我认为这不是 RESTful 方式。由于friends 本身就是一个资源,您可能希望公开它并直接访问它,即:

    GET friends/{UserID-1};{UserID-2};{UserID-3}
    

    这里需要注意一件重要的事情 - 在前面的示例中,我在用户 ID 之间使用了 ;,而在上面的 fields 示例中使用了 ,。原因是两者都代表不同的运算符。在第一种情况下,我们需要 OR (,) 来获取所有三个字段,而在上面的最后一个示例中,我们必须使用 AND (;) 来获取交集。

    使用两种类型的运算符可能会使 API 设计过于复杂,但最终应该提供更大的灵活性。

    【讨论】:

      【解决方案3】:

      感谢您的澄清回答。它们正是我所要求的。不幸的是,我没有时间从头到尾阅读“RESTful Web Services”。但我会尽快赶上。 :-)

      关于我帖子的第一部分:

      你是对的。我倾向于您的第一个示例,并且没有字段。我认为我根本不需要它。 (目前)您为什么建议使用 OR (,) 而不是 AND (;)?直觉上,我会使用 AND 运算符,因为我想要所有三个,而不仅仅是第一个存在。 (如第 121 页上的颜色对示例)

      关于第二部分:

      {Value-1/2} 仅指 URI 的 url 编码值,而不是它们的响应数据。 :) 这里我倾向于你的第二个例子。在这里应该很明显,在计算相交朋友时,实际上涉及到一个算法。除此之外,我可能还会向它添加一些进一步的操作。

      宠物

      【讨论】:

      • (#1) 我将其视为 OR 的原因是您想要获取所有三个 - 姓名、年龄或性别。使用 AND 不会返回任何一个,因为这三个字段之间没有交集(而在第二部分中,我们正在寻找交集。(#2)是处理它的一种方法,但请注意,如果您向其中添加更多逻辑,您仍然应该致力于让 intersection 关键字在您的整个 API 中始终如一地工作(即像 field 关键字一样)。跨度>
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-15
      • 2010-11-29
      • 1970-01-01
      • 1970-01-01
      • 2014-10-12
      • 2015-01-01
      • 1970-01-01
      相关资源
      最近更新 更多