**为什么接口返回 415 Unsupported Media Type?**
415 错误表示客户端请求的资源格式(Content-Type)不被服务器支持。常见原因包括:① 前端未设置或错误设置 `Content-Type` 请求头(如发送 JSON 数据却未设为 `application/json`);② 后端框架(如 Spring Boot、Express、Django REST Framework)严格校验 `Content-Type`,而客户端传入了不匹配类型(如用 `text/plain` 提交 JSON);③ 客户端实际发送的数据格式与声明的 `Content-Type` 不一致(如声明 `application/json` 却发送了表单编码数据);④ API 文档要求特定媒体类型(如 `application/vnd.api+json`),但调用方未遵循。该状态码是 HTTP/1.1 标准定义的语义化响应,强调“服务端拒绝处理此格式”,而非数据内容错误(那是 400)。排查时应优先比对请求头、请求体、接口契约三者是否一致。
1条回答 默认 最新
小小浏 2026-01-30 18:30关注```html一、HTTP 415 状态码的本质:语义化契约的断裂
415 Unsupported Media Type 是 RFC 7231 定义的 HTTP/1.1 标准状态码,其核心语义是服务端明确拒绝处理当前请求体(payload)的媒体类型——它不质疑数据合法性(那是 400 Bad Request 的职责),而是断言“我根本不认识你声称的这种格式”。这本质上是客户端与服务端在
Content-Type协议层的契约失效,属于典型的“接口契约违规”,而非业务逻辑错误。二、四维归因模型:从表象到根因的系统性拆解
- 前端请求头缺失或错配:如使用
fetch()提交 JSON 时未显式设置headers: {'Content-Type': 'application/json'},导致浏览器默认发送text/plain或空值; - 后端框架强校验机制触发:Spring Boot 的
@RequestBody默认要求application/json;Express 中express.json()中间件仅解析匹配该类型的请求;Django REST Framework 的JSONParser同样严格比对; - 请求体与声明类型严重失配:例如声明
Content-Type: application/json,但实际发送的是username=john&password=123(即application/x-www-form-urlencoded),此时 JSON 解析器会直接抛出格式异常; - API 版本化/定制化媒体类型未遵循:如 OpenAPI 规范中定义的
application/vnd.myapp.v2+json,客户端若仅传application/json,Spring MVC 的@RequestMapping(produces = "application/vnd.myapp.v2+json")将拒绝响应。
三、跨技术栈典型场景与验证代码
技术栈 错误示例 修复方案 Spring Boot @PostMapping("/api/user") public User create(@RequestBody User user)+ 前端发text/plain添加 @RequestMapping(consumes = MediaType.APPLICATION_JSON_VALUE)显式约束,或全局配置spring.mvc.contentnegotiation.favor-parameter=falseVue + Axios axios.post('/api/login', {pwd: '123'}, {headers: {}})axios.post('/api/login', {pwd: '123'}, {headers: {'Content-Type': 'application/json'}})四、深度排查流程图(Mermaid)
flowchart TD A[捕获 415 响应] --> B{检查 Request Headers} B -->|无 Content-Type?| C[前端补全 header] B -->|Content-Type 存在| D{是否匹配 API 文档契约?} D -->|否| E[修正为文档指定类型 e.g. application/vnd.api+json] D -->|是| F{请求体格式是否真实一致?} F -->|JSON 字符串?| G[确认无多余空格/非法字符/UTF-8 BOM] F -->|表单数据?| H[改用 application/x-www-form-urlencoded] G --> I[重试并抓包验证] H --> I五、高阶陷阱与五年以上开发者需警惕的细节
- 代理/网关二次篡改:Nginx 或 API Gateway 可能因配置
proxy_set_header Content-Type ""清除原始头; - 浏览器 DevTools 的“假象”:Network 面板显示的
Content-Type是请求发起时的快照,若 JS 动态修改 header 失败(如 CORS 预检被拒),实际发出的请求可能无此头; - Spring Boot 2.6+ 的严格模式:默认启用
spring.web.resources.add-to-cart=true并强化 media type 匹配,需配合@RequestPart处理 multipart 混合内容; - curl 调试的隐式行为:使用
curl -d '{"a":1}'默认设Content-Type: application/x-www-form-urlencoded,必须显式加-H "Content-Type: application/json"; - Swagger UI 的默认行为偏差:部分旧版 Swagger 在未配置
consumes时自动填充application/json,但后端未开放该类型,造成“文档可调通、代码调不通”的幻觉。
六、防御性设计建议(面向架构师与资深工程师)
在微服务治理层面,建议在 API 网关层注入统一的
```Content-Type校验熔断策略,并记录X-Content-Type-Mismatch自定义头用于链路追踪;后端服务应通过 OpenAPI 3.0 的requestBody.content显式声明支持类型,配合契约测试(如 Dredd)实现 CI/CD 阶段自动拦截不合规调用。对于遗留系统升级,可采用 Spring Boot 的WebMvcConfigurer注册自定义HandlerExceptionResolver,将 415 错误增强为包含可读提示(如“期望 application/json,收到 text/plain,请检查请求头与序列化方式”)的 JSON 响应,显著降低一线运维排障成本。本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报- 前端请求头缺失或错配:如使用