使用 HTTP 204 vs 200 vs 404 来安全地表示资源不存在
Use of HTTP 204 vs 200 vs 404 to safely signal that a resource doesn't exist
在我的 REST API 中,我有一些资源的正常 CRUD 端点。
如果我执行 GET /items/42
并且没有这样的项目,则正常行为将是 return 和 404 NOT FOUND
。
但是,有一种情况与我有关。在这种情况下,客户端需要检查资源(由令牌隐式标识)是否存在,如果不存在,则创建它。因此,客户端将尝试检索资源,如果收到 404
,客户端应用程序将显示创建项目所需的 UI,然后继续 POST
ing 新的资源。在某种程度上,这是一种特殊的资源,因为它的 ID 是从其他参数派生的,所以它甚至在创建之前就已经知道了。例如,考虑用户注册过程;客户会问 "Do I exist? If no -> register me".
我真正担心的是我是否需要担心 "spurious" 404
:s?考虑到服务器通常被 API 网关、反向代理等包围,是否存在由于某些与 REST 服务器本身无关的临时错误而导致周围实体产生 404 NOT FOUND
的风险?如果是这样,它可能会诱使客户相信该项目尚未创建,现在应该创建它。即使生成的 POST
创建项目的请求会因为项目已经存在而失败,这也不是很好,因为用户可能无缘无故地输入了数据等。
这是一个需要考虑的问题还是过于偏执?我想如果客户不能相信 404
是幂等的(当然,在创建资源之前),就会出现许多其他问题。是否存在 API 网关或类似网关会自行报告 404
的实际情况?
如果这是一个有效的场景,我是否需要 "safer" 更明确的响应,说明请求肯定成功但未找到资源,例如用 200 OK
响应空 JSON 正文或 {isRegistered: false}
、204 NO CONTENT
或类似内容?这为其他奇怪的事情打开了大门 - 如果对不存在的资源的请求将以 200
伴随着空主体响应,那么该项目的 creation 可能会是 PUT
而不是 POST
,等等?这似乎是一堆蠕虫......这一切都归结为 "Does a 404
guarantee that the given resource doesn't exist?".
404 非常明确:找不到资源,它是 client error (4xx)。通常,服务器端错误 (5xx) 不会干扰并在此处创建虚假 404。
作为替代方案,如果要创建的资源以唯一方式链接到另一个资源,您可以使用 OPTIONS 询问服务器它是否已经存在。
例如:
OPTIONS /visitors/7883930/user-account
=> Allow: POST,OPTIONS
(不存在)
=> Allow: GET,OPTIONS
(存在)
这里的关键是要有一个允许在不知道其 ID 的情况下访问资源的 URI。不过,这并不总是可能的。
在我的 REST API 中,我有一些资源的正常 CRUD 端点。
如果我执行 GET /items/42
并且没有这样的项目,则正常行为将是 return 和 404 NOT FOUND
。
但是,有一种情况与我有关。在这种情况下,客户端需要检查资源(由令牌隐式标识)是否存在,如果不存在,则创建它。因此,客户端将尝试检索资源,如果收到 404
,客户端应用程序将显示创建项目所需的 UI,然后继续 POST
ing 新的资源。在某种程度上,这是一种特殊的资源,因为它的 ID 是从其他参数派生的,所以它甚至在创建之前就已经知道了。例如,考虑用户注册过程;客户会问 "Do I exist? If no -> register me".
我真正担心的是我是否需要担心 "spurious" 404
:s?考虑到服务器通常被 API 网关、反向代理等包围,是否存在由于某些与 REST 服务器本身无关的临时错误而导致周围实体产生 404 NOT FOUND
的风险?如果是这样,它可能会诱使客户相信该项目尚未创建,现在应该创建它。即使生成的 POST
创建项目的请求会因为项目已经存在而失败,这也不是很好,因为用户可能无缘无故地输入了数据等。
这是一个需要考虑的问题还是过于偏执?我想如果客户不能相信 404
是幂等的(当然,在创建资源之前),就会出现许多其他问题。是否存在 API 网关或类似网关会自行报告 404
的实际情况?
如果这是一个有效的场景,我是否需要 "safer" 更明确的响应,说明请求肯定成功但未找到资源,例如用 200 OK
响应空 JSON 正文或 {isRegistered: false}
、204 NO CONTENT
或类似内容?这为其他奇怪的事情打开了大门 - 如果对不存在的资源的请求将以 200
伴随着空主体响应,那么该项目的 creation 可能会是 PUT
而不是 POST
,等等?这似乎是一堆蠕虫......这一切都归结为 "Does a 404
guarantee that the given resource doesn't exist?".
404 非常明确:找不到资源,它是 client error (4xx)。通常,服务器端错误 (5xx) 不会干扰并在此处创建虚假 404。
作为替代方案,如果要创建的资源以唯一方式链接到另一个资源,您可以使用 OPTIONS 询问服务器它是否已经存在。
例如:
OPTIONS /visitors/7883930/user-account
=> Allow: POST,OPTIONS
(不存在)
=> Allow: GET,OPTIONS
(存在)
这里的关键是要有一个允许在不知道其 ID 的情况下访问资源的 URI。不过,这并不总是可能的。