Accept头仅指定application/json时,返回application/problem+json是否合法?
我正在构建API端点,打算采用application/problem+json(参考RFC 7807)格式返回错误响应,示例如下:
HTTP/1.1 401 Unauthorized Content-Type: application/problem+json; charset=utf-8 Date: Wed, 07 Aug 2019 10:10:06 GMT { "type": "https://example.com/probs/cant-view-account-details", "title": "Not authorized to view account details", "status": 401, "detail": "Only users with the role administrator are allowed to do this.", "instance": "/account/123456/details" }
我的疑问是:在可接受响应媒体类型层面,application/problem+json是否可被视为application/json的(子)类型?也就是当请求的Accept头仅指定application/json而未包含application/problem+json时,返回该类型的响应是否合法?
已知它的编码与片段标识符规则和application/json完全一致,也看到过「以+json结尾的Content-Type基本被当作application/json处理」的说法,但没有官方文档支撑。从语法上看,任何problem+json内容都是合法的JSON,因此有人认为接受application/json意味着也接受前者;但根据RFC 7231,子类型无层级关系,Accept头明确指定可接受的响应媒体类型,而非匹配内容的类型,所以我不确定规范的API是否应该这么做。
严格遵循HTTP规范的话,这种做法不合法:根据RFC 7231的定义,
Accept头匹配的是明确声明的媒体类型,子类型之间不存在层级继承关系。application/problem+json是独立的媒体类型,和application/json属于同级范畴,除非请求的Accept头使用了通配符(比如application/*或者*/*),否则仅指定application/json的请求,返回application/problem+json不符合规范要求。实际场景中多数客户端能兼容,但不能依赖:因为
application/problem+json的内容本身是合法的JSON结构,大部分HTTP客户端会忽略Content-Type中的后缀部分,直接按JSON解析内容。但这属于客户端的容错行为,并非规范强制要求,不能保证所有严格遵循规范的客户端都能正常处理。规范API的建议做法:
- 在API文档中明确说明错误响应采用
application/problem+json格式,引导客户端在Accept头中主动包含该类型; - 若要兼容仅发送
application/json的请求,可以做兼容处理:当Accept头包含application/problem+json时返回对应类型,否则返回结构一致但Content-Type为application/json的错误响应; - 不要默认给仅请求
application/json的客户端返回application/problem+json,避免触发严格遵循HTTP规范的客户端报错。
- 在API文档中明确说明错误响应采用
内容的提问来源于stack exchange,提问作者buddemat

