如何在设计 RESTful API 时解决不明确的 404
How to address ambiguous 404s when designing a RESTful API
我在为我正在开发的 REST API 编写测试和文档时遇到过这种奇怪的情况。根据这个 REST tutorial,在 RESTful API 中利用的一个关键抽象是资源的概念,一个常见的模式是让资源本身包含自己的资源。此外,returning 404
为实际上并不存在的 ID 资源也是一种常见模式。
我的问题是考虑到 REST API.
的层次结构,404
响应代码可能会模棱两可。
例如,假设我们的 REST API 与之交互的数据层具有以下数据:
{
"users": {
"foo": {
"notes": {
"hello": "world"
}
}
}
}
调用我们的 REST API return 200
意味着路径中的所有资源都存在:
GET /users/foo
returns 200
因为用户 foo
存在。
GET /users/foo/notes
returns 200
同理
GET /users/foo/notes/hello
returns 200
因为用户foo
和都属于一个名为hello
的笔记到 foo
两者都存在。
特定路径甚至有预期的 404
响应代码:
GET /users/bar
returns 404
。这是明确的,因为 404
仅指一个资源。
GET /users/bar/notes
returns 404
。这同样明确(假设 API 对于不存在的路径不 return 404
)。
但是考虑以下 return 404
出于不同和模棱两可的原因:
GET /users/bar/notes/baz
returns 404
因为用户bar
不存在
GET /users/foo/notes/baz
returns 404
因为现有用户 foo
没有 baz
注释。
简而言之,404
s returned 不会通知客户端究竟找不到什么:用户或注释。所以我的问题如下:
服务器是否有责任明确 404
响应代码?如果是这样,它应该如何向客户端区分用户不存在与用户注释不存在?
Is it the responsibility of the server to be nonambiguous with 404 response codes? And if so, how should it differentiate to the client the nonexistence of a user versus the nonexistence of a user's note?
如 RFC 7231.
中所述,通过提供“包含对错误情况的解释以及它是临时还是永久情况的表示”
换句话说,将解释性详细信息放入您包含在 HTTP 响应中的文档中。
更仔细地思考所有这些如何与网页一起工作可能会有所帮助。
状态代码是 transfer of documents over a network domain. The intended audience for that information is the web browser (and other general purpose components - spiders, caches, and so on). It's provided so that your browser (and other general purpose components) can correctly interpret 响应语义中的元数据。
“错误表示”的受众是使用网络浏览器的人。在这里,人们可以提供有关特定问题或可能采取的纠正措施的信息。
在现代,我们通常期望定制的机器客户端而不是人类来查看“网络浏览器”。自由格式文本或标有超媒体控件的自由格式文本不太可能有用。所以我们可能想使用 problem details - 报告问题的标准化模式。
您可能遇到的一个困难(不是您的错;文献很烂)是认识到标识符在语义上是不透明的。 /users/foo/notes/baz
通常不依赖于 /users/foo/notes
或任何其他前缀。标识符也不意味着 /users/foo/notes/baz
有四个不同的部分需要满足。
标识符应理解为 map/dictionary 中的键 - 200 表示键存在于映射中,404 表示键不存在于映射中。但这实际上并不能告诉您是否存在具有相似拼写的其他键的任何信息!
您的 API 是否比使用非常规资源模型的 API 更“好”?和任意标识符?应该是吧。
但是好的资源模型和好的标识符拼写约定 不是 REST 约束,并且 HTTP 和 URI 规范还支持不遵循当前约定的设计(以及其他事情,向后兼容性对 REST 和 web 真的 很重要;REST 和 web 比这些拼写约定早了很多)。
(打个比方:我们有围绕变量命名和函数命名等想法描述“最佳实践”的编码约定,因为我们使用的语言不限制我们使用“好”名称。机器不在乎。 )
我在为我正在开发的 REST API 编写测试和文档时遇到过这种奇怪的情况。根据这个 REST tutorial,在 RESTful API 中利用的一个关键抽象是资源的概念,一个常见的模式是让资源本身包含自己的资源。此外,returning 404
为实际上并不存在的 ID 资源也是一种常见模式。
我的问题是考虑到 REST API.
的层次结构,404
响应代码可能会模棱两可。
例如,假设我们的 REST API 与之交互的数据层具有以下数据:
{
"users": {
"foo": {
"notes": {
"hello": "world"
}
}
}
}
调用我们的 REST API return 200
意味着路径中的所有资源都存在:
GET /users/foo
returns200
因为用户foo
存在。GET /users/foo/notes
returns200
同理GET /users/foo/notes/hello
returns200
因为用户foo
和都属于一个名为hello
的笔记到foo
两者都存在。
特定路径甚至有预期的 404
响应代码:
GET /users/bar
returns404
。这是明确的,因为404
仅指一个资源。GET /users/bar/notes
returns404
。这同样明确(假设 API 对于不存在的路径不 return404
)。
但是考虑以下 return 404
出于不同和模棱两可的原因:
GET /users/bar/notes/baz
returns404
因为用户bar
不存在GET /users/foo/notes/baz
returns404
因为现有用户foo
没有baz
注释。
简而言之,404
s returned 不会通知客户端究竟找不到什么:用户或注释。所以我的问题如下:
服务器是否有责任明确 404
响应代码?如果是这样,它应该如何向客户端区分用户不存在与用户注释不存在?
Is it the responsibility of the server to be nonambiguous with 404 response codes? And if so, how should it differentiate to the client the nonexistence of a user versus the nonexistence of a user's note?
如 RFC 7231.
中所述,通过提供“包含对错误情况的解释以及它是临时还是永久情况的表示”换句话说,将解释性详细信息放入您包含在 HTTP 响应中的文档中。
更仔细地思考所有这些如何与网页一起工作可能会有所帮助。
状态代码是 transfer of documents over a network domain. The intended audience for that information is the web browser (and other general purpose components - spiders, caches, and so on). It's provided so that your browser (and other general purpose components) can correctly interpret 响应语义中的元数据。
“错误表示”的受众是使用网络浏览器的人。在这里,人们可以提供有关特定问题或可能采取的纠正措施的信息。
在现代,我们通常期望定制的机器客户端而不是人类来查看“网络浏览器”。自由格式文本或标有超媒体控件的自由格式文本不太可能有用。所以我们可能想使用 problem details - 报告问题的标准化模式。
您可能遇到的一个困难(不是您的错;文献很烂)是认识到标识符在语义上是不透明的。 /users/foo/notes/baz
通常不依赖于 /users/foo/notes
或任何其他前缀。标识符也不意味着 /users/foo/notes/baz
有四个不同的部分需要满足。
标识符应理解为 map/dictionary 中的键 - 200 表示键存在于映射中,404 表示键不存在于映射中。但这实际上并不能告诉您是否存在具有相似拼写的其他键的任何信息!
您的 API 是否比使用非常规资源模型的 API 更“好”?和任意标识符?应该是吧。
但是好的资源模型和好的标识符拼写约定 不是 REST 约束,并且 HTTP 和 URI 规范还支持不遵循当前约定的设计(以及其他事情,向后兼容性对 REST 和 web 真的 很重要;REST 和 web 比这些拼写约定早了很多)。
(打个比方:我们有围绕变量命名和函数命名等想法描述“最佳实践”的编码约定,因为我们使用的语言不限制我们使用“好”名称。机器不在乎。 )