【问题标题】:RESTful API required parameters in query string?查询字符串中的 RESTful API 必需参数?
【发布时间】:2015-04-19 20:57:50
【问题描述】:

在设计 RESTful API 时,如果 GET 请求仅在与请求关联的特定参数时才有意义,该怎么办?参数是否应该作为查询字符串传递,如果是,当所有参数未指定或格式不正确时该怎么办?

例如,假设我有一个 Post 资源,可以通过 `api/posts` 端点访问。每个帖子都有一个地理位置,只有在指定帖子可能驻留的区域时才能检索帖子。因此,需要三个参数:纬度、经度和半径。

在这种情况下,我可以想到 2 个选项:
1. 将参数放入查询字符串中:api/posts/?lat=5.54158&lng=71.5486&radius=10
2. 将参数放入URL:api/posts/lat/5.54158/lng/71.5486/radius/10

以下哪种方法是正确的?将所需参数放在查询字符串中似乎是错误的,但后一种方法感觉有点“丑陋”。

PS。我知道已经有很多关于这个主题的讨论(例如:REST API Best practices: Where to put parameters?),但我的问题专门针对需要参数而不是可选参数的情况。

【问题讨论】:

标签: rest


【解决方案1】:

在设计 RESTful API 时,如果 GET 请求只发出 感觉是否有与请求相关的特定参数? 参数是否应该作为查询字符串传递,如果是,要传递什么 未指定所有参数或未格式化时执行 错了吗?

通过 REST,您的 API 必须满足 REST 约束,这些约束在 Fielding dissertation 中进行了描述。这些约束之一是统一接口约束,其中包括HATEOAS constraint。根据 HATEOAS 约束,您的 API 必须提供标准超媒体格式作为响应。该超媒体包含用元数据(例如链接关系或 RDF 注释)注释的超链接(例如 HTML 链接、表单)。客户端检查元数据,向他们解释超链接的作用。之后,他们可以决定是否要关注该链接。当他们点击链接时,他们可以根据 URI 模板、参数等构建 HTTP 请求并将其发送到 REST 服务。

在您的情况下,您使用哪种 URI 结构并不重要,它仅用于服务使用,因为客户端始终使用给定的 URI 模板,并且客户端不关心该模板中的内容,直到它是有效的 URI 模板它可以用参数填充。

在大多数情况下,您的客户有足够的验证信息来测试参数是否不正确或缺失。在这种情况下,它不会发送 HTTP 请求,因此您在服务中无事可做。如果无效参数通过,那么在您的情况下,您的服务会发回 404 - 未找到,因为 URI 是资源标识符,并且没有资源属于无效 URI(从给定的 URI 模板和无效参数生成)。

【讨论】:

  • 但是,也建议在参数值与现有资源不对应时返回404错误时,应使用路径段参数。看看以下问题的第一个答案:stackoverflow.com/questions/4024271/…
  • @StenSootla 你是对的“服务器没有找到任何匹配请求 URI 的东西。没有指示条件是临时的还是永久的。”所以在这种情况下 404 是好的响应。 400 是格式错误的请求正文。
  • 对不起,我不太明白你的最后评论。您是说我应该将参数作为查询字符串传递(因为参数不是分层的),当其中一些参数丢失或格式错误时,我应该发回带有 404 状态码的响应。但是,如果您查看我在之前的评论中提到的另一个 stackoverflow 问题,那里的最佳回答者明确表示,当返回 404 错误时,参数应该是 url 路径的一部分,而不是查询字符串。
  • @StenSootla 我猜你误会了。 404 不应该有实体。我说的是客户端用来构建 URI 的表单描述,也应该包含验证数据。
  • 是的,我当然也在验证数据客户端。但这并不意味着我不应该设计我的 REST api 来处理错误参数仍然通过的情况。我想我完全错过了你的观点:d?
【解决方案2】:

您应该将所有内容都放在查询字符串中,并设置服务器在未收到 3 个必需参数时返回错误代码。

因为它是一组标识一个对象的参数。

举个例子: 纬度=5.54158; lng=71.5486 半径=10

这个网址不太可能有意义:

api/posts/lat/5.54158/lng/yyyy/radius/zz

不同于:

api/memb/35/..

因为 id 为 35 的成员可以有很多功能(所以,有效的 url):

api/memb/35/statusapi/memb/35/lastlogin

【讨论】:

  • 查询参数应该过滤和缩小使用 GET /resources 调用执行的搜索。丢失时返回错误意味着这不仅仅是一个过滤器,而是合同的一部分,这对客户来说似乎是一种误导。如果您错过了查询参数,您可以只返回一个空响应,因为没有与给定条件匹配的资源(例如 lat=xxx 但未知长度)
【解决方案3】:

第一种方法更好。

api/posts/?lat=5.54158&lng=71.5486&radius=10



第二种方法有点误导。

api/posts/lat/5.54158/lng/71.5486/radius/10

您应该将每个目录视为资源。在这个原因中,子资源(例如:“api/posts/lat/5.54158”)并不是真正的资源,因此会产生误导。在某些情况下,这种模式是更好的解决方案,但看看给出的内容,我会使用查询字符串。除非您有一些实体链接可以将您直接链接到此 URL,否则我不太喜欢它。

【讨论】:

  • +1! path/uri 参数用于访问特定资源,而查询参数用于过滤资源
猜你喜欢
  • 1970-01-01
  • 2018-04-14
  • 1970-01-01
  • 1970-01-01
  • 2012-06-15
  • 1970-01-01
  • 1970-01-01
  • 2018-04-15
  • 1970-01-01
相关资源
最近更新 更多