如何在设计RESTful API时解决模棱两可的404



我在为正在开发的REST API编写测试+文档时遇到了这个奇怪的场景。根据本REST教程,在RESTful API中要利用的一个关键抽象是资源的概念,而一种常见的模式是使资源本身包含自己的资源。此外,为实际上并不存在的ID资源返回404也是一种常见的模式。

我的问题来自这样一个事实,即考虑到RESTneneneba API的层次结构性质,404响应代码可能是不明确的。

例如,假设我们的REST API交互的数据层具有以下数据:

{
"users": {
"foo": {
"notes": {
"hello": "world"
}
}
}
}

对返回200的REST API的调用意味着路径中的所有资源都存在:

  • GET /users/foo返回200,因为用户foo存在
  • CCD_ 7返回CCD_
  • 因为用户foo都存在属于foo的名为hello的音符,所以GET /users/foo/notes/hello返回200

对于特定路径,甚至还有预期的404响应代码:

  • GET /users/bar返回404。这是不含糊的,因为404仅引用一个资源
  • CCD_ 18返回CCD_。这同样是明确的(假设API不会为不存在的路径返回404)

但考虑到以下返回404的原因不同且不明确:

  • GET /users/bar/notes/baz返回404,因为用户bar不存在
  • 由于现有用户foo没有baz钞票,GET /users/foo/notes/baz返回404

简而言之,返回的404s不会通知客户端到底是什么找不到:用户还是笔记。所以我的问题如下:

服务器是否有责任与404响应代码保持一致?如果是这样的话,它应该如何向客户区分不存在用户和不存在用户笔记?

服务器是否有责任对404响应代码保持不含糊?如果是这样的话,它应该如何向客户区分不存在用户和不存在用户笔记?

通过提供";包含对错误情况的解释以及它是暂时的还是永久的条件的表示";如RFC 7231中所述。

换句话说,将解释性细节放入HTTP响应中包含的文档中。


更仔细地思考这一切如何与网页协同工作可能会有所帮助。

状态代码是通过网络域传输文档时的元数据。这些信息的目标受众是web浏览器(以及其他通用组件——蜘蛛、缓存等等)。它的提供是为了让您的浏览器(和其他通用组件)能够正确地解释响应的语义。

观众为";误差的表示";是使用网络浏览器的人。例如,在那里,人们可以提供关于具体出了什么问题的信息,或者可以采取什么纠正措施。

在现代,我们通常期待定制机器的客户,而不是人类,来关注";网络浏览器";。自由形式文本或用超媒体控件标记的自由形式文本不太可能有用。因此,我们可能希望使用问题细节——一种用于报告问题的标准化模式。


你可能遇到的一个困难(不是你的错;文献很糟糕)是识别标识符在语义上是不透明的。/users/foo/notes/baz通常不依赖于/users/foo/notes或任何其他前缀。标识符也不意味着/users/foo/notes/baz具有需要满足的四个不同部分。

标识符应该像地图/字典中的键一样被理解——200表示键存在于地图中,404表示键不存在于地图上。但这实际上并不能告诉你是否存在其他拼写相似的键!

是您的API吗?它按照惯例将其资源模型组织成一个层次结构,并选择与该层次结构紧密一致的标识符;"更好";而不是使用非常规资源模型和任意标识符的API?可能

但是,良好的资源模型和良好的标识符拼写约定不是REST约束,HTTP和URI规范也支持不遵循当前约定的设计(除其他外,向后兼容性对REST和web非常重要;REST和web在很大程度上早于这些拼写约定)。

(类比:我们有围绕变量命名和函数命名等思想描述"最佳实践"的编码约定,因为我们使用的语言不限制我们使用"好"名称。机器不在乎。)

最新更新