普通网友 2026-01-30 18:30 采纳率: 98.5%
浏览 0
已采纳

为什么接口返回 415 Unsupported Media Type?

**为什么接口返回 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 协议层的契约失效,属于典型的“接口契约违规”,而非业务逻辑错误。

    二、四维归因模型:从表象到根因的系统性拆解

    1. 前端请求头缺失或错配:如使用 fetch() 提交 JSON 时未显式设置 headers: {'Content-Type': 'application/json'},导致浏览器默认发送 text/plain 或空值;
    2. 后端框架强校验机制触发:Spring Boot 的 @RequestBody 默认要求 application/json;Express 中 express.json() 中间件仅解析匹配该类型的请求;Django REST Framework 的 JSONParser 同样严格比对;
    3. 请求体与声明类型严重失配:例如声明 Content-Type: application/json,但实际发送的是 username=john&password=123(即 application/x-www-form-urlencoded),此时 JSON 解析器会直接抛出格式异常;
    4. 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=false
    Vue + Axiosaxios.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 响应,显著降低一线运维排障成本。

    ```
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 1月31日
  • 创建了问题 1月30日