REST API DESIGN-使用不同的参数但相同的 URL 模式通过 REST 获取资源

我有一个关于 RESTURL 设计的问题。我在这里发现了一些相关的文章 同一资源的不同 RESTful 表示形式和这里的 通过不同字段获取资源的 RESTful url,但是对于什么是最佳实践以及为什么是最佳实践的答复并不十分清楚。举个例子。

我有表示“用户”资源的 REST URL。我可以得到一个用户与 ID 或电子邮件地址,但 URL 表示保持相同的两个。通过阅读大量的博客和书籍,我发现人们已经在以许多不同的方式做这件事。比如说

在一本书和堆栈溢出的某处读到这个实践(我似乎找不到这个链接了)

GET /users/id={id}
GET /users/email={email}

在很多博客上读到过这种做法

GET /users/{id}
GET /users/email/{email}

查询参数通常用于过滤由 URL 表示的资源的结果,但我也看到过这种做法

GET /users?id={id}
GET /users?email={email}

我的问题是,在所有这些实践中,哪一个对于使用 API 的开发人员来说最有意义,为什么?我相信在 REST URL 设计和命名约定方面没有一成不变的规则,但是我只是想知道我应该采取哪种方式来帮助开发人员更好地理解 API。

90965 次浏览

根据我的经验,GET /users/{id} GET /users/email/{email}是最常用的方法。如果提供的 idemail不存在用户,我还希望这些方法返回一个404 Not Find。看到 GET /users/id/{id}我也不会感到惊讶(尽管在我看来,它是多余的)。

对其他方法的评论

    • 我觉得我没见过这个,如果我真的看到了,那就太让人困惑了。它几乎像是试图用路径参数模拟查询参数。
    • 我认为您在提到使用查询参数进行过滤时一语中的。
    • 使用 都有idemail(例如 GET /users?id={id}&email={email})来调用这个资源有意义吗?否则,我不会使用这样的单一资源方法。
    • 我希望这种方法可以检索带有可选查询参数的用户的 名单,但我不希望参数中包含 idemail或任何唯一标识符。例如: GET /users?status=BANNED可能返回一个被禁用户列表。

从相关问题中查看 这个答案

从实用的角度来看,你得到了一组用户:

/users   # this returns many

每个用户都有一个专用的资源位置:

/users/{id}    # this returns one

你还有很多方法来搜索用户:

/users?email={email}
/users?name=*bob*

因为这些都是/用户的查询参数,所以它们都应该返回列表. . 即使列表为1。

我在这里写了一篇关于实用的 RESTful API 设计的博客文章,其中谈到了 http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api

关于用户资源

辛格尔顿

/users/[user_id]路径上,你可以预期会发生几件事,例如:

  • 您应该获得一个单例资源,它表示具有标识符[ user _ id ]或
  • 如果不存在具有 id [ user _ id ]的用户或者没有找到 404响应
  • 如果不允许访问请求的用户资源,则返回禁用的 401

每个单例模式都通过其路径和标识符进行唯一标识,您可以使用这些标识符来查找资源。不可能为单例模式使用多个路径。

收集

在路径 /users上,您将始终获得返回的用户资源的集合。

可以使用查询参数(GET参数)查询路径 /users。这将返回一个包含满足请求条件的用户的集合。返回的集合应包含用户资源,所有这些资源在响应中都具有标识资源路径。搜索参数可以是集合资源中存在的任何字段; firstNamelastNameid

例如:

/users?id=1
/users?firstName=John
/users?lastName=Doe

或者甚至是上述因素的组合:

/users?firstName=John&lastName=Doe

集合响应始终是一个数组。数组可以是空的(不匹配) ,包含一个项目(决定性的)或几个项目(非决定性的)。

关于那封邮件

电子邮件可以是资源,也可以是用户资源的属性/字段。

- 作为用户财产的电子邮件:

如果字段是用户的属性,那么用户的响应如下所示:

{
id: 1,
firstName: 'John'
lastName: 'Doe'
email: 'john.doe@example.com'
...
}

这意味着电子邮件没有特殊的端点,但是你现在可以通过发送以下请求通过电子邮件找到一个用户: /users?email=john.doe@example.com. 它(假设电子邮件对于用户是唯一的)将返回一个集合,其中包含一个与电子邮件匹配的用户项。

- 电子邮件资源:

但如果来自用户的电子邮件也是资源。然后,您可以创建一个 API,其中 /users/[user_id]/emails返回 id 为 user_id的用户的电子邮件地址集合。/users/[user_id]/emails/[email_id]返回具有 user _ id 和[‘ em ail _ id’]的用户的电子邮件。你用什么标识符取决于你,但我会坚持使用整数。您可以通过向要删除的电子邮件的路径发送 DELETE请求来删除用户的电子邮件。 因此,例如 /users/[user_id]/emails/[email_id]上的 DELETE将删除具有 email _ id 的电子邮件,该电子邮件由具有 user _ id 的用户所拥有。很可能只允许该用户执行此删除操作。其他用户将得到一个401响应。

如果一个用户只能有一个电子邮件地址,你可以坚持 /users/[user_id]/email 这将返回一个单例资源。用户可以通过 PUTting 该网址的电子邮件地址来更新他的电子邮件地址。