HTTPQUERY
English

406 Not Acceptable

用法

收到 406 Not Acceptable 错误时,该响应由 Accept 或 Accept-Language 之类的协商相关头触发。当客户端包含一个或多个这类头时,服务器会在可能的情况下满足这些要求。

最常见的 HTTP Accept 头有:

Accept:指定首选的内容类型。服务器可提供纯文本或 HTML 表示。在本例中,客户端首选 HTML,但也接受纯文本。

Accept: text/html, text/plain

Accept-Encoding:指定客户端接受的编码。在本例中,客户端表明支持 gzip 压缩。

Accept-Encoding: gzip

实践中,此错误很少被使用,因为服务器通常会转而提供一个默认表示。其背后的理念假设客户端宁可要一些东西也不愿一无所获。当确实返回 406 Not Acceptable 响应时,消息体中包含一个可用表示的列表,供客户端从中选择。

注意

406 Not Acceptable 意味着服务器无法生成与客户端 Accept 头匹配的响应(输出格式问题)。415 Unsupported Media Type 意味着服务器无法理解请求体的 Content-Type(输入格式问题)。406 关乎客户端想要接收什么,而 415 关乎客户端发送了什么。

SEO 影响

像 Google 这样的搜索引擎不会索引返回 406 Not Acceptable 状态的 URL。此前已被索引、如今返回该状态码的 URL 会从搜索结果中移除。

示例

客户端请求法语版本的资源,但由于只有德语和英语版本可用,服务器返回 406 Not Acceptable。

请求

GET /news HTTP/1.1
Host: example.com
Accept-Language: fr

响应

HTTP/1.1 406 Not Acceptable
Content-Type: text/html
Content-Length: 242

<html>
  <head>
    <title>French Language Not Available</title>
  </head>
  <body>
    <p>Please choose a supported language:</p>
    <p><a href="/news/news-de.html">German</a></p>
    <p><a href="/news/news-en.html">English</a></p>
  </body>
</html>

如何修复

406 Not Acceptable 意味着服务器没有任何与客户端内容协商头匹配的表示。

审查 Accept 头。放宽可接受的媒体类型。例如,在 text/html 之外添加 application/json,或使用 / 来接受任何格式。使用浏览器开发者工具(Network 标签页)或 curl -v 检查客户端发送的确切 Accept 头。

检查 Accept-Language 约束。请求服务器不支持的语言会触发此错误。扩大语言列表,或添加通配符(*)作为回退。浏览器语言设置会自动控制该头。可在浏览器的语言首选项中进行调整。

移除过于严格的 Accept-Encoding 或 Accept-Charset 值。狭窄的编码或字符集要求会限制服务器的选择。允许常见值,如 gzip、deflate 和 UTF-8。

检查响应体中的可用替代项。服务器通常会在 406 响应中列出支持的表示。选择其一并相应调整协商头。

检查服务端的内容协商配置。服务器上配置错误的类型映射或缺失的 MIME 类型注册会导致意外的 406 响应。在 Apache 中,mod_negotiation 和 MultiViews 控制类型映射。核实 AddType 指令已注册所需的 MIME 类型。

检查 mod_security 或 WAF 规则。Apache 的 mod_security(及类似 WAF)会拦截请求,并在规则针对请求内容(而非 Accept 头)触发时返回 406。检查服务器错误日志中的 ModSecurity 条目,并记下规则 ID(如 [id “941160”])。将特定规则加入白名单,而不是完全禁用 WAF:

SecRuleRemoveById 941160

将该排除项放入虚拟主机配置或 .htaccess 文件中。

用最简请求进行测试。剥离所有协商头,用 curl 发送一个裸请求,以判断服务器是否返回默认表示。如果裸请求成功,再逐个加回协商头,以隔离出触发拒绝的那个头。

核实 API 版本协商。有些 API 使用 Accept 头进行版本控制(如 application/vnd.api.v2+json)。发送不受支持的版本字符串会产生 406。对照 API 文档确认版本值。

代码参考

.NET

HttpStatusCode.NotAcceptable

Rust

http::StatusCode::NOT_ACCEPTABLE

Rails

:not_acceptable

Go

http.StatusNotAcceptable

Symfony

Response::HTTP_NOT_ACCEPTABLE

Python3.5+

http.HTTPStatus.NOT_ACCEPTABLE

Java

java.net.HttpURLConnection.HTTP_NOT_ACCEPTABLE

Apache HttpComponents Core

org.apache.hc.core5.http.HttpStatus.SC_NOT_ACCEPTABLE

Angular

@angular/common/http/HttpStatusCode.NotAcceptable