我们正在开发一个RESTful api,它以JSON编码数据的形式接受请求中的查询参数。
我们想知道非请求/非预期参数与所需参数一起传递时的正确行为。
例如,我们可能要求给定端点上的PUT请求必须分别为键名称和姓氏提供两个值:
{
"name": "Jeff",
"surname": "Atwood"
}
如果虚假键也被传递,如下例中的颜色,该怎么办?
{
"name": "Jeff",
"surname": "Atwood",
"color": "red"
}
颜色的值不是预期的,也没有记录。
我们应该忽略它还是拒绝BAD_REQUEST 400状态错误的请求?
我们可以断言请求是坏的,因为它不符合文档。可能API用户应该被警告(她传递了价值,她会期待一些东西。)
但我们也可以断言请求可以被接受,因为,因为所有参数都已提供,所以可以实现。
答案 0 :(得分:34)
多年来使用过来自众多供应商的RESTful API,让我给你一个“用户”的观点。
很多时候,文档很糟糕或过时了。可能参数名称已更改,也许您在属性名称上强制使用了完整的大小写,也许您在文档中使用了错误的字体,并且 I 看起来与 l 完全相同 - 是的,那些是不同的字母。
不要忽略它。而是发回错误消息,说明属性名称,并带有易于理解的消息。例如“未知属性名称:颜色”。
这一小事将大大限制消耗API的支持请求。
如果您只是忽略这些参数,那么开发人员可能会认为在引用您的API时传入了有效值,因为显然 API无法正常工作。
如果你抛出一般性错误消息,那么你就会让开发人员试图找出正在发生的事情并充斥你的论坛,这个网站或你的手机会打电话询问为什么你的服务器无法工作。 (我最近遇到了这个问题,供应商只是不明白404消息不是对错误参数的有效响应,而且文档应该反映使用的实际参数名称......)
现在,出于同样的原因,我希望您在缺少必需参数时也能提供良好的错误消息。例如“必需属性:名称缺失”。
基本上,您希望尽可能提供帮助,以便API的使用者尽可能自给自足。正如你所言,我全心全意地不同意“亲切”与“严厉”的崩溃。您越“亲切”,您的API消费者就越有可能遇到他们认为他们正在做正确的事情但却从您的API中获得意外行为的问题。你无法想到人们会搞砸所有可能的方式,所以强制严格遵守相关的错误信息将会有很大的帮助。
答案 1 :(得分:17)
如果您进行API设计,您可以遵循两条路径:“严厉”或“亲切”。
REST允许一个非常优雅的API设计,我会尝试尽可能长时间地遵循这条路径并期望我的客户一样。如果我的API发展,我可能必须在我的响应中添加仅与特定客户相关的其他参数。如果我的客户对我很慷慨,他们将能够处理这个问题。 话虽如此,我想补充说,有一个严格的API设计的地方。如果您在敏感域(例如现金交易)中进行设计,并且您不希望为客户端和服务器之间的任何误解留出空间。想象一下以下POST请求(对您的/ account / {no} / transaction / API有效):
{ amount: "-100", currency : "USD" }
您将如何处理以下(无效的API请求)?
{ amount: "100", currency : "USD", type : "withdrawal" }
如果您只是忽略“类型”属性,您将存入100美元而不是取消它们。在这样的领域,我会遵循严厉的方法,并且不会表现出任何优雅。
如果可以的话,请保持仁慈,如果必须,请严厉。
<强>更新强>
我完全同意@Chris Lively's answer应告知用户。我不同意它应该始终是一个错误的情况,即使消息对于引用的资源是非模糊的。否则,这将阻碍资源表示的重用,并需要重新打包语义相同的信息。
答案 2 :(得分:0)
请忽略它们。
不要让用户有机会通过错误消息对RESTful API进行反向工程。
为开发人员提供最新,最清晰,最全面的文档,并仅解析API所需和支持的参数。
答案 3 :(得分:0)
这取决于你的文件..你想要多严格..
但一般来说,只是ignore
它。大多数其他服务器也忽略它不理解的请求参数。
从我之前的帖子中取得的例子
Extra Query parameters in the REST API Url
“”“Google在此忽略我的两个额外参数https://www.google.com/#q=search+for+something&invalid=param&more=stuff”“”
答案 4 :(得分:0)
想象一下,我有以下JSON架构:
{
"frequency": "YEARLY",
"date": 23,
"month": "MAY",
}
frequency属性接受“WEEKLY”,“MONTHLY”和“YEARLY”值。 “WEEKLY”频率值的预期有效载荷是:
{
"frequency": "WEEKLY",
"day": "MONDAY",
}
“MONTHLY”频率值的预期有效载荷是:
{
"frequency": "MONTHLY",
"date": 23,
}
给出上面的JSON模式,通常我需要一个包含频率,日期,日期和月份字段的POJO来进行反序列化。
如果收到的有效载荷是:
{
"frequency": "MONTHLY",
"day": "MONDAY",
"date": 23,
"year": 2018
}
我会在“day”属性上抛出错误,因为我永远不会知道发件人的意图:
对于“年”属性,我真的没有选择。 即使我希望为该属性抛出错误,我也许无法做到。 它被JSON序列化/反序列化库忽略,因为我的POJO没有这样的属性。这是GSON的行为,鉴于设计决策,它是有意义的。
在反序列化时导航Json树或目标类型树
当您将Json字符串反序列化为所需类型的对象时,您可以导航输入树或所需类型的类型树。 Gson使用后一种方法来导航目标对象的类型。这使您可以严格控制仅实例化您期望的对象类型(实质上根据预期的“模式”验证输入)。通过这样做,您还可以忽略Json输入但不期望的任何额外字段。
作为Gson的一部分,我们编写了一个通用的ObjectNavigator,可以接受任何对象并在其字段中导航,调用您选择的访问者。
答案 5 :(得分:-1)
我建议您忽略额外的参数。重用API是整合世界中的游戏规则改变者。如果其他集成可以使用相同的API,但有一些额外的参数,该怎么办?
申请A期待:
{
"name": "Jeff",
"surname": "Atwood"
}
申请B期待:
{
"name": "Jeff",
"surname": "Atwood",
"color": "red"
}
简单获取应用程序应用程序A忽略“颜色”将完成工作而不是有2个不同的API来处理它。