当它应该返回 400 错误请求时,Restlet 是不是返回 415 不支持的媒体类型?

Posted

技术标签:

【中文标题】当它应该返回 400 错误请求时,Restlet 是不是返回 415 不支持的媒体类型?【英文标题】:Is Restlet returning 415 Unsupported Media Type when it should return 400 Bad Request?当它应该返回 400 错误请求时,Restlet 是否返回 415 不支持的媒体类型? 【发布时间】:2011-05-17 13:23:55 【问题描述】:

我正在使用带有 jackson 的 Restlet 2.1 来构建一个 json REST api。

当我使用预期的内容类型但正文格式不正确时,我会返回 415“不支持的媒体类型”状态代码。我认为正确的错误代码应该是 400 "Bad Request"。

显然,当杰克逊尝试解码垃圾但未能成功时,就会发生混淆。

我会尝试用一些代码使情况更清楚:

// java method mapping
@Post("json")
public Project create(Project project) 

使用 curl 调用服务

$ curl -i -XPOST -H 'content-type: application/json' -d 'xgarbage' http://localhost:8080/projects HTTP/1.1 415 Unsupported Media Type

还有一段堆栈跟踪操作系统记录在日志中:

Nov 29, 2010 9:51:56 PM org.restlet.ext.jackson.JacksonRepresentation getObject
WARNING: Unable to parse the object with Jackson.
org.codehaus.jackson.JsonParseException: Unexpected character ('x' (code 120)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
 at [Source: java.io.ByteArrayInputStream@693e4a5a; line: 1, column: 2]
at org.codehaus.jackson.JsonParser._constructError(JsonParser.java:929)

服务的实际实现永远不会受到影响,因此在某个地方做出了将乱码内容映射到 415 的决定。

现在,我的问题是:这是正确的吗?如果我正确阅读了“RESTful Web Services”一书中的以下引文,那不是,但我愿意更正。

[400 Bad Request] 常用于客户端连同 PUT 或 POST 请求一起提交表示,并且表示格式正确,但没有任何意义。

.

[415 Unsupported Media Type] 如果客户端发送的文档具有正确的媒体类型但格式错误(例如使用错误词汇表编写的 XML 文档),更好的响应是更通用的 400(“Bad Request ”)

对与错,我宁愿返回 400。

有没有办法改变行为而不放弃杰克逊提供的自动魔法序列化?

非常感谢任何帮助, 谢谢!

【问题讨论】:

【参考方案1】:

415 是正确的,因为如果请求已损坏,则请求的格式正确。例如不可解析的 JSON 或 XML。根据定义,格式错误的 JSON 或 XML NOT JSON 或 XML,因此是不受支持的媒体类型,Jackson 无法知道它应该是 JSON,它只知道它不是它可以解析的 JSON。

官方documentation对此非常清楚。

10.4.16 415 不支持的媒体类型

服务器拒绝为请求提供服务,因为请求实体的格式不受所请求方法的请求资源支持。

你说,嘿,这是 JSON,但服务器不是这样说的,嘿,我得到的不是 JSON,并且不受此资源的支持。

【讨论】:

我想这是有争议的:格式和良好的格式是两件不同的事情(你可以有一个损坏的 jpg)。我认为服务器应该发出不同的信号“嘿,你试图发送应用程序/foo,我不支持它”和“是的,我们确实支持 json,但你的数据已损坏”。 解析器如何知道某些东西是 json 但已损坏,这就像 jpg 解码器说这是 jpg 但已损坏,这没有任何意义,解码器或解析器只能说我尝试过要将其解析为某种东西并且它是不可解析的,无法解码为图像的位块不是 jpg,如果不能这样解析,则非文本块不是 json。 嗯,这就是 Content-Type http 标头的用途:它声明了预期的内容类型。如果发送者声明它是 json,但解码器不能这样解码,那么这是一个错误的请求,因为它没有任何意义。这不是一个糟糕的媒体类型(因为预期的媒体类型会很好)。 key 是“...in a format not supported by the requested resource for the requested method”损坏的输入满足此要求。 事实是 corrupt 是无关紧要的,解析器不知道它是错误的格式还是只是一个损坏的格式 格式错误 从解析器的角度来看。软件就是这样愚蠢的。 400 如果对于格式错误的 syntax,这意味着在 语义上 不同于损坏。

以上是关于当它应该返回 400 错误请求时,Restlet 是不是返回 415 不支持的媒体类型?的主要内容,如果未能解决你的问题,请参考以下文章

AJAX请求返回HTTP 400 错误 - 请求无效 (Bad request)

AJAX请求返回HTTP 400 错误 - 请求无效 (Bad request)

Google 地理编码服务返回错误 400 错误请求

发生错误 400(错误请求)时,使用 Axios 从 POST 捕获返回 json

浏览器中返回的状态码400是啥?

Instagram API 返回 400(错误请求)