RESTful API需要在查询字符串中使用哪些必需参数?

29
设计RESTful API时,如果只有特定参数与GET请求相关,应该怎么做?应该将参数传递为查询字符串吗?如果是这样,那么当没有指定或格式不正确时该怎么办?
例如,假设我有一个Post资源,可以通过`api/posts`端点访问。每个帖子都有地理位置,并且仅在指定帖子可能驻留的区域时才能检索到帖子。因此,需要3个参数:纬度、经度和半径。
在这种情况下,我可以想到两个选项: 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最佳实践:放置参数的位置?),但我的问题专门针对必需参数的情况。

http://programmers.stackexchange.com/questions/270898/designing-a-rest-api-by-uri-vs-query-string - Robert Rowntree
3个回答

25

第一种方法更好。

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
+1!路径/ URI 参数用于访问特定资源,而查询参数用于过滤资源。 - Kevin K.

7
你应该将所有内容放在查询字符串中,并设置服务器在未接收到3个必需参数时返回错误代码。
因为这是一组用于标识对象的参数。
以以下示例为例:lat=5.54158;lng=71.5486;radius=10
这个URL很不可能有意义:api/posts/lat/5.54158/lng/yyyy/radius/zz
与此不同的是:api/memb/35/...
因为具有ID 35的会员可以拥有许多功能(因此有效的URL),例如:
api/memb/35/status 或 api/memb/35/lastlogin

查询参数应该用于过滤和缩小使用GET /resources调用执行的搜索范围。如果缺少查询参数就返回错误,这意味着它们不仅仅是过滤器,而且是合同的一部分,这对客户来说有点误导。如果您错过了查询参数,可以返回一个空响应,因为没有资源与给定的条件匹配(例如lat=xxx但未知long)。 - Carmine Ingaldi

3
设计RESTful API时,如果GET请求只有在请求中存在特定参数时才有意义,应该怎么办?这些参数应该作为查询字符串传递,如果所有参数没有被指定或格式不正确应该怎么办?
按照REST的约束条件,你的API必须满足描述在Fielding dissertation中的REST约束条件之一是统一接口约束条件,其中包括HATEOAS约束条件。根据HATEOAS约束条件,你的API必须提供标准的超媒体格式作为响应。这个超媒体包含了注释有元数据(如链接关系或RDF注释)的超链接(例如HTML链接、表单)。客户端检查元数据,解释超链接的功能。然后他们可以决定是否要跟随链接。当他们跟随链接时,他们可以基于URI模板、参数等构建HTTP请求并将其发送到REST服务。
在您的情况下,使用哪种URI结构并不重要,它仅用于服务使用,因为客户端始终使用给定的URI模板,并且客户端不关心该模板中包含什么内容,直到它是一个有效的URI模板,可以用参数填充。
在大多数情况下,您的客户端具有足够的验证信息来测试参数是否不正确或缺失。在这种情况下,它不会发送HTTP请求,因此在服务中没有任何事情可做。如果无效的参数通过,则在您的情况下,您的服务将发送回404-未找到,因为URI是资源标识符,并且无资源属于无效的URI(从给定的URI模板和无效的参数生成)。

1
但是,建议在参数值不对应现有资源时返回404错误时使用路径段参数。请查看以下问题的第一个答案:https://dev59.com/tm865IYBdhLWcg3wBJ4q - stensootla
@StenSootla 您说得对,“服务器未找到与请求URI匹配的任何内容。没有指示条件是暂时的还是永久的。” 所以在这种情况下,404是正确的响应。 400是由于错误格式的请求正文。 - inf3rno
@StenSootla,我想你误解了。404不应该有正文。我说的是客户端用来构建URI的表单描述,也应包含验证数据。 - inf3rno
当然,我也在客户端验证数据。但这并不意味着我不应该设计我的REST API来处理仍然通过的不正确参数的情况。我想我完全没有理解你的观点 :d ? - stensootla
@StenSootla,你必须处理这种情况,但我认为一个没有响应主体的404足够了。由于URI是资源标识符,并且您无法使用错误的参数识别资源。我会再次阅读您的问题,也许我的回答中遗漏了一些内容。 - inf3rno
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接