rest - 设计 RESTful API 时如何解决模棱两可的 404
问题描述
在为我正在开发的 REST API 编写测试 + 文档时,我遇到了这个奇怪的场景。根据这个REST 教程,在 RESTful API 中利用的一个关键抽象是资源的概念,一个常见的模式是让资源本身包含自己的资源。此外,返回404
一个实际上并不存在的 ID 资源也是一种常见的模式。
我的问题来自这样一个事实,即404
考虑到 REST API 的分层性质,响应代码可能会模棱两可。
例如,假设我们的 REST API 与之交互的数据层具有以下数据:
{
"users": {
"foo": {
"notes": {
"hello": "world"
}
}
}
}
调用返回的 REST API200
意味着路径中的所有资源都存在:
GET /users/foo
200
因为用户foo
存在而返回。GET /users/foo/notes
200
出于同样的原因返回。GET /users/foo/notes/hello
返回200
,因为用户foo
和一个名为hello
属于foo
两者的便笺都存在。
甚至有404
特定路径的预期响应代码:
GET /users/bar
返回404
。这是明确的,因为404
only 指的是一种资源。GET /users/bar/notes
返回404
。这同样明确(假设 API 不返回404
不存在的路径)。
但请考虑以下404
由于不同且模棱两可的原因而返回的情况:
GET /users/bar/notes/baz
404
因为用户bar
不存在而返回。GET /users/foo/notes/baz
404
因为现有用户foo
没有baz
注释而返回。
简而言之,404
返回的 s 不会通知客户端究竟是什么未能找到:用户或便笺。所以我的问题如下:
服务器是否有责任明确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 和网络比这些拼写约定早了很多)。
(类比:我们有围绕变量命名和函数命名等想法描述“最佳实践”的编码约定,因为我们使用的语言不限制我们使用“好”名称。机器不在乎。)
推荐阅读
- ms-access - 访问自定义功能区 (USysRibbons) 上的 PDF 按钮
- python-3.x - 如何使 Python 中的代码更高效,因为该程序会为大型输入数据集提供时间执行错误
- php - 如何让 jQuery 在返回之前等待 Ajax 调用完成
- c++ - 是 reinterpret_cast
(myTypePtr) 假设指向一个数组? - c++ - 如何将零填充的多维数组传递给 C++ 中的函数?
- javascript - React Router DOM 仅在需要时加载组件
- python - 用于合并特定行的 Pandas Dataframe 操作
- c# - 如何从 Business Central 获取数据?
- c# - Excel/VSTO:错误 0x80028018 仅在直接绑定到 interop.-provided 属性时
- python - 获取与语句匹配的数组中的任何元素