我们正在开发一个标准 REST 服务,使用 HTTP 状态代码作为出现问题时的响应代码。 (例如,无效的用户输入将向客户端返回“400 Bad Request”)
但是,我们认为更详细的错误消息对客户端会很有用。 (例如,无效输入错误是由于 X 是无法识别的参数名称)
我们希望尽可能忠实于 HTTP 规范,因此在研究了 RFC2616,我们正在考虑将详细的错误消息放在 HTTP 标头中,特别是在 HTTP 标头警告字段。它在 RFC 上说:
警告通用标头字段用于携带有关消息状态或转换的附加信息,这些信息可能不会反映在消息中。此信息通常用于警告缓存操作或应用于消息实体正文的转换可能缺乏语义透明度。
将此标头用于其他警告(例如 REST 错误消息)似乎没有限制,即使是根据此标头的初衷与缓存警告无关的警告。我们喜欢这种语义,并且计划使用 299 警告代码,这似乎非常符合要求:
299 其他持续警告警告文本可能包含要呈现给人类用户或记录的任意信息。收到此警告的系统不得采取任何自动操作。
因此,考虑到本问题顶部出现的无效输入错误情况,我们正在考虑将 REST 错误消息设置为如下例所示:
HTTP/1.1 400 Bad Request
Warning: 299 ServiceName "Invalid input error: X is unrecognized parameter name."
这是一个好主意/做法吗?我们还发现一些服务在 X-Warning 标头中详细说明了此消息,但这似乎不标准。我们想知道 stackoverflow REST 人群的蜂巢智慧会对此有何看法。是否还有更好/标准化的实践来在 REST 响应中传递详细的错误消息?
We are developing a standard REST service using HTTP status codes as its response code if something went wrong. (e.g. invalid user input would return "400 Bad Request" to the client)
However, we felt that a more detailed error message would be useful for the client. (e.g. the invalid input error is due to X being a unrecognized parameter name)
We would like to be as faithful to the HTTP specs as possible, so after studying the specification in the RFC2616, we are thinking of putting the detailed error message in the HTTP Headers, specifically on the HTTP header warning field. It said on the RFC that:
The Warning general-header field is used to carry additional information about the status or transformation of a message which might not be reflected in the message. This information is typically used to warn about a possible lack of semantic transparency from caching operations or transformations applied to the entity body of the message.
There seems to be no restriction on using this header for other warnings (such as REST error message), even those that are unrelated with the cache warnings as per the original intention of this header. We like the semantic, and we planned to use the 299 warning code, which seems to fit the bill quite nicely:
299 Miscellaneous persistent warning The warning text MAY include arbitrary information to be presented to a human user, or logged. A system receiving this warning MUST NOT take any automated action.
So, given the invalid input error case presented on the top of this question, we're thinking of putting our REST error message like the following example:
HTTP/1.1 400 Bad Request
Warning: 299 ServiceName "Invalid input error: X is unrecognized parameter name."
Is this a good idea/practice? We also found that some services detailed this message in X-Warning header, but this seems to be not standard. We are wondering what would the hive wisdom of stackoverflow REST crowd think about this. Is there also any better/standardized practice for passing out detailed error messaging in REST responses?
发布评论
评论(7)
为什么不直接改变原因短语呢?这就是它的用途。 “错误请求”文本只是默认文本。如果您想包含更多信息,请使用响应正文。 HTTP 规范规定您应该包含包含错误详细信息的响应正文。
更新
根据最近对 RFC 7231 和相关材料的阅读,更改原因短语的唯一有效原因似乎是本地化文本,而不是提供更具体的含义。对此感到抱歉。
Why not just change the reason phrase? That's what it is there for. The "Bad Request" text is just the default. If you want to include more information then use the response body. The HTTP spec says you SHOULD include a response body with details of an error.
UPDATE
Based on a more recent reading of RFC 7231 and related material, it appears the only valid reason for changing the reason phrase is to localize the text, not to provide a more specific meaning. Sorry about that.
无论您将反馈放在何处,无论是在消息正文(内容)中还是在警告标头中,请小心避免提供任何可能有助于攻击者在您的系统上进行渗透测试的信息。
有时信息越少越好。
Wherever you put your feedback, whether in the message body (content) or in a Warning header, be careful to avoid giving any information that might be helpful to an attacker doing penetration testing on your system.
Sometimes less info is better.
我赞成仅在请求成功时才使用标头进行警告。
例如,一项服务获取用户的详细信息,但其中一些详细信息来自第三方,而这些信息经常会出现故障。在我们的例子中,将用户数据的该部分留空是合适的,但向用户显示某些数据丢失的警告。
因此,该请求返回了 200 Success,其有效负载包含我们可以检索的所有内容,但随后包含描述其余错误的警告标头。
I'm in favor of using headers for warning only when the request succeeds in general.
For example a service that get's a user's details, but some of the details come from a third party which often goes down. In our case it was appropriate to leave that section of the user data blank, but show a warning to the user that some data is missing.
So the request returned a 200 Success with a payload that contained everything we could retrieve, but then had warning headers that described the error for the rest.
我赞成一般方法。我们应该假设客户端开发人员与服务开发人员位于不同的团队中,可能位于不同的时区等。甚至可能是不同的公司。仅仅返回“不,这是一个错误的请求”响应是没有用的,客户端如何解决问题。
所以从哲学上讲:告诉客户他们有责任解决哪些问题。纯粹是服务器范围内的错误(例如数据库连接错误或某些逻辑问题),返回 500 错误是公平的。在这里我不会发回任何细节,我们不想向客户公开我们内部实现的细节。
到目前为止,我一直在使用 JAX/RS 返回响应正文中的数据:
我认为您使用标头实际上可能是一种更干净的方法。
I'm in favour of the general approach. We should assume that the client developer is in a different team from the service developer, maybe in a different timezone etc. Possibly even a different company. It's no good just returning a "no that's a bad request" response, how can the client fix the problem.
So philosophically: tell the client about the things they have a responsibility to fix. Errors that are purely the scope of the server (eg. database connection error, or some logical problem) it's fair just to return a 500 error. And here I would not send any detail back, we don't want to expose details of our internal implementation to the client.
Until now I've been returning data in the body of the response, using JAX/RS:
I'm thinking that your use of headers may actually be a cleaner appraoch.
如果此提案被接受,它会提出一个替代方案用于发送详细错误消息。 [https://datatracker.ietf.org/doc/html /draft-nottingham-http-browser-hints]
尽管它是一个 ID,但最近它相当稳定,我认为构建自己的实现没有问题。 (我已经做到了。)
If this proposal is accepted, it presents an alternative for sending detail error messages. [https://datatracker.ietf.org/doc/html/draft-nottingham-http-browser-hints]
Despite it being an I-D, it's fairly stable lately, and I see no problem with building your own implementation. (I have done.)
Warning
HTTP 标头 可能是 由于缺乏客户端支持,已于 2022 年弃用。(不过,它将来总是可以重新激活或改变用途,因此我对在封闭生态系统之外更改语义非常谨慎。)
似乎有一个标准轨道“拟议标准” RFC 专门用于此类事情:
虽然自 2021 年初以来就没有更新过,但还有 draft-cedik-http-warning - 在 HTTP API 中传达警告信息正在讨论 在 GitHub 上。
The
Warning
HTTP header is likely to be deprecated in 2022 due to lack of client support.(It could always be reactivated or repurposed in the future, though, so I would be quite wary about changing the semantics outside of a closed ecosystem.)
There appears to be a standards-track “Proposed Standard” RFC purpose-made for this sort of thing:
Although it hasn’t been updated since early 2021, there is also draft-cedik-http-warning - Communicating Warning Information in HTTP APIs under discussion on GitHub.
429 请求过多 (RFC 6585)
用户在给定时间内发送了太多请求。旨在与速率限制方案一起使用。
由于您在每个生命周期允许一个请求,因此您正在实施速率限制方案,因此这是适当的 HTTP 响应。
您还可以(HTTP 规范鼓励)自定义 HTTP 响应正文,这样您就可以将“太多请求”更改为您想要的任何解释。
429 Too Many Requests (RFC 6585)
The user has sent too many requests in a given amount of time. Intended for use with rate limiting schemes.
Since you are allowing one request per lifetime, you are implementing a rate limiting scheme, so this is the appropriate HTTP response.
You can also (and are encouraged by the HTTP spec) to customize the HTTP Response body, so you can change "Too Many Requests" to any explanation you want.