406 Not Acceptable: 是什么及如何解决

January 25, 2018 Andrew Powell-Morse

406 Not Acceptable是一个HTTP响应状态码,指示服务器无法实现客户端的一个 Accept-标头的请求响应。这通常是用户代理(即浏览器)指定一个可接受的字符集(通过Accept-Charset)、语言(通过Accept-Language)等应响应的结果,并且服务器无法提供此类响应。

与大多数 HTTP 响应代码一样 — 尤其是那些指示错误的响应代码 — 406 Not Acceptable 错误代码的原因可能难以跟踪和修复。具有 50 多个状态代码的潜在池,这些代码表示客户端、Web 应用程序、Web 服务器以及通常有多个第三方 Web 服务之间的复杂关系,这导致了在最佳情况下,确定特定状态代码的原因可能是一项挑战。

在本文中,我们将通过查看可能导致消息的原因,以及一些用于诊断和调试此错误在您自己的应用程序中出现的错误提示来更详细地检查 406 Not Acceptable的内容。我们甚至会检查一些最流行的内容管理系统 (CMS),以发现可能导致您自己的网站意外生成 406 Not Acceptable 的潜在问题区域。让我们钻研一下吧!

服务端-还是客户端?

4xx 类别中的所有 HTTP 响应状态代码都被视为客户端错误响应。此类别与 5xx 分类错误(如我们几个月前探索的 504 网关超时错误)形成鲜明对比,这些错误被视为服务器错误响应。也就是说,出现 4xx 错误并不一定意味着问题出在客户端,这里的"客户端"是指用于访问应用程序的 Web 浏览器或设备。通常,如果您尝试在您自己的应用程序中诊断问题,可以立即忽略大多数客户端代码和组件,如 HTML、级联样式表 (CSS)、客户端 JavaScript 等等。这也不仅仅适用于网站。许多实现时髦用户界面的智能手机应用程序实际上由后台的正常 Web 应用程序提供支持,而这些应用程序只是对用户来说简单地隐藏起来而已。

另一方面,服务器可能是 406 Not Acceptable 错误的根本原因。在某些情况下,服务器可能配置错误,并且不正确地处理了请求,这可能导致 406 代码响应和其他有疑问的流量路由问题。我们将在下面探讨其中一些场景(和潜在的解决方案),但请注意,即使 406 Not Acceptable 被视为客户端错误响应,在这个场景下它本质上并不意味着我们可以排除客户端或服务器作为此问题的罪魁祸首。在这些场景下,服务器仍然是生成 406 Not Acceptable 的网络对象,并将其作为 HTTP 响应代码返回给客户端,但可能是客户端以某种方式导致这个问题的。

从全面应用备份开始

和任何事情一样,最好在开始的时候就安全地玩转起来,而不是把事情搞砸,然后不久以后在路上后悔。因此,在尝试对系统进行任何修复或更改之前,对你的应用程序、数据库以及网站或应用程序的所有其他组件执行完整备份至关重要。更妙的是,如果你有能力,请创建应用程序的完整备份,并将这个备份存储在非活动或公众无法访问的辅助暂存服务器上。这将为您提供一个干净的测试场,用于测试解决问题的所有潜在修补程序,而不会威胁实时应用程序的安全性或神圣性。

诊断一个406 Not Acceptable 错误

如简介中所述,406 Not Acceptable 表示用户代理(在大多数情况下是 Web 浏览器)请求了有效的资源,但请求包含一个特殊的 Accept- 标头,该标头向服务器指示有效响应只能包含特定类型的信息。下面是此类场景的几个栗子:

  • 用户代理可能本地化为服务器无法提供的特定区域设置或语言。例如,用户代理可以使用 Accept-Language 请求标头来指定有效的法语语言(Accept-Language:fr),但如果服务器无法使用法语提供响应,则 406 代码可能是唯一正确的响应。
  • 用户代理可能请求服务器返回特定类型的内容。这些内容类型通常称为 MIME 类型,用于定义如纯文本(text/plain)、PNG 图像(image/png)、mp4 视频(video/mp4)等内容。因此,客户端可以在请求中包含 Accept 标头,并定义应由服务器提供的显式 MIME 类型(例如,Accept:application/xml)。如果服务器无法响应请求的匹配内容类型,则可能需要 406 Not Acceptable 响应。

在 HTTP 请求中可以提供少量其他 Accept- 标头,但绝大多数场景与上述类似:用户代理需要显式类型的响应,服务器要么提供响应,要么返回 406 代码以指示它无法实现请求。

客户端故障排除

既然 406 Not Acceptable 是客户端错误响应代码,因此最好首先排除可能导致此错误的任何潜在客户端问题。下面是一些提示,用于在出现问题的浏览器或设备上尝试下。

检查请求的URL

406 Not Acceptable 的最常见原因是仅仅输入了不正确的 URL。许多服务器都受到严密保护,因此不允许对客户端/用户代理不应访问的资源发出意外请求。可能是请求的 URL 稍有错误,从而导致用户代理请求特定类型的响应。例如,对 URI https://airbrake.io?json 的请求可能会向服务器指示需要 JSON 响应。由于 406 代码不如 404 代码常见,因此 406 的出现可能意味着请求的 URL 有效,但浏览器可能会误解预期的请求类型。无论采用哪种方式,仔细检查返回 406 Not Acceptable 错误的确切 URL以确保它是预期资源是一个好主意。

调试通用平台

如果你在得到 406 Not Acceptable 响应的服务器上运行常见软件包,则可能需要首先查看这些平台的稳定性和功能。最常见的内容管理系统——如 WordPress、Joomla!和 Drupal——通常都是经过精心测试的,但一旦您开始对基础扩展或 PHP 代码(这个语言几乎用在所有现代内容管理系统)进行了修改,将很容易导致不可预见的问题,进而导致 406 Not Acceptable 错误。

下面有几个提示,旨在帮助您解决这些流行的软件平台故障。

回滚最近升级

如果您最近刚好在 406 Not Acceptable 错误出现之前更新了内容管理系统本身,您可能需要考虑回滚到在工作正常时安装的早期版本。同样,您最近升级的任何扩展或模块也可能导致服务器端问题,因此还原到这些扩展或模块的早期版本也可能有所帮助。要获得此任务的帮助,只需使用搜索"降级 [平台名称]"然后跟进即可。然鹅,在某些情况下,某些 CMSs 并不真正提供版本降级功能,这表明他们认为基本应用程序以及发布的每个新版本都极其稳定且无错误。对于较流行的平台,典型情况就是如此,所以如果您找不到将平台还原到旧版本的简单方法,请不要害怕。

卸载新扩展、模块或插件

根据您的应用程序使用的特定内容管理系统,这些组件的确切名称将有所不同,但它们在每个系统中都具有相同的用途:改进平台的功能和特性,使其超出其通常的预期。但请注意:这些扩展或多或少可以完全控制系统,并几乎可以进行任何更改,无论是对 PHP 代码、HTML、CSS、JavaScript 还是数据库。因此,卸载最近可能添加的任何新扩展可能是明智的。再说一次,通过搜索这些扩展的名称以获取这个进程的官方文档和协助。

检查意外的数据库更改

值得注意的是,即使您通过 CMS 仪表板卸载了扩展,也不保证该扩展所做的更改已完全还原。对于许多 WordPress 扩展来说尤其如此,这些扩展在应用程序中提供全权委托,包括数据库的完全访问权限。除非扩展作者在代码中显式编码此类内容,否则在某些场景下,扩展可能会修改不"属于"扩展本身,而是由其他扩展(甚至基本 CMS 本身)创建和管理的数据库记录。在这些情况下,扩展可能不知道如何还原对数据库记录的更改,因此在卸载期间将忽略此类内容。诊断此类问题可能比较棘手,但我本人多次遇到此类情况,因此,假设您有理由相信扩展可能是 406 Not Acceptable 的罪魁祸首,因此,您的最佳操作方案是打开数据库,手动查看可能由扩展修改的表和记录。

最重要的是,不要害怕搜索你的问题。尝试搜索与您的问题相关的特定术语,例如应用程序的 CMS 名称随同 406 Not Acceptable。你很有可能会找到经历过同样问题的人。

服务器端的故障排除

如果您未运行 CMS 应用程序——或者即使您运行了 CMS 应用程序,但您确信 406 Not Acceptable 与该应用程序无关——下面是一些其他提示,可帮助您解决在服务器端可能导致的此类问题。

确认您的服务器配置

您的应用程序可能在使用两个最流行的 Web 服务器软件之一 Apache 或 nginx 的服务器上运行。在发布时,这两个网络服务器软件占了世界上所有网络服务器软件的 84%!因此,您可以采取的第一步,以确定是什么可能导致这些 406 Not Acceptable 响应代码是检查您的 Web 服务器软件的配置文件是否无意的重定向或请求处理指令。

要确定您的应用程序正在使用哪个Web 服务器,您需要查找一个密钥文件。如果您的 Web 服务器是 Apache,则在网站文件系统的根目录中查找 .htaccess 文件。例如,如果您的应用程序位于共享主机上,则可能具有与托管帐户关联的用户名。在这种情况下,应用程序根目录通常位于 /home//public_html/的路径上,因此 .htaccess 文件将在 /home//public_html/.htaccess 处。

如果找到 .htaccess 文件,然后在文本编辑器中打开该文件,并查找使用 RewriteXXX 指令的行,这些指令是 Apache 中mod_rewrite模块的一部分。但是,涵盖这些规则如何工作完全超出了本文的范围,但基本概念是,RewriteCond 指令定义了一个基于文本的模式,该模式将与输入的 URL 匹配。如果站点的访问者请求了匹配的 URL,则遵循一个或多个 RewriteCond 指令的 RewriteRule 指令用于执行请求到相应 URL 的实际重定向。

例如,下面是一个简单的RewriteRule,它匹配所有传入中不包含Accept:application/json 标头的请求到https://airbrake.io/users/json。结果是重定向和 406 Not Acceptable 的响应错误代码:

RewriteEngine on
RewriteCond %{REQUEST_URI} ^/users/json/?.*$
RewriteCond %{HTTP_ACCEPT} !application/json
RewriteRule ^(.*)$ http://airbrake.io/users/json$1 [R=406,L]

请注意RewriteRule末尾的 R=406 标志,该标志明确声明响应代码应为 406,向用户代理指示资源存在,但无法实现显式 Accept- 标头。因此,如果您在 .htaccess 文件中发现任何看似非我同类的奇怪的 RewriteCond 或 RewriteRule 指令,请尝试暂时注释掉它们(使用 # 字符前缀),然后重新启动 Web 服务器以查看这是否解决了问题。

另一方面,如果您的服务器在 nginx 上运行,则需要查找完全不同的配置文件。默认情况下,此文件名为 nginx.conf,位于几个通用目录之一:/usr/local/nginx/conf、/etc/nginx 或 /usr/local/etc/nginx。找到以后,在文本编辑器中打开 nginx.conf 并查找使用 406 响应代码标志的指令。例如,下面是一个简单的块指令(即一组命名的指令),该指令为airbrake.io配置虚拟服务器,并确保与上述类似,对不包括Accept:application/json 请求标头至 https://airbrake.io/users/json 的请求将会失败,并且返回 406 响应代码:

server {     
    listen 80;    
    listen 443 ssl;        
    server_name airbrake.io;        
    location /users/json 
    {        
        if ($http_accept != application/json) 
        {            
        	return 406 https://airbrake.io/users/json$request_uri;        
        }    
    }
}

请查看 nginx.conf 文件,了解包含 406 标志的任何异常指令或行。在重新启动服务器之前注释掉任何异常,以查看问题是否得到解决。

每种不同类型的 Web 服务器的配置选项可能巨大差异,因此,我们将仅列出一些流行的项目,以便为您提供一些资源,具体取决于您的应用程序在哪种类型的服务器上运行:

  • Apache
  • Nginx
  • IIS
  • Node.js
  • Apache Tomcat

查看日志

几乎每个 Web 应用程序都会保留某种形式的服务器端日志。应用程序日志通常是应用程序所执行操作的历史记录,例如请求了哪些页面、它连接到哪些服务器、它提供的哪些数据库结果,等等。服务器日志与运行应用程序的实际硬件相关,并且通常会提供有关所有已连接服务的运行状况和状态的详细信息,甚至仅提供服务器本身的详细信息。如果您使用的是 CMS,搜索"日志 平台名称";如果您正在运行自定义应用程序,则使用"日志 编程语言"和"日志 操作系统"来进行搜索,以获取有关查找出现问题相关日志的详细信息。

调试应用程序代码或脚本

如果所有其他操作都失败,可能是应用程序中某些自定义代码中的问题导致了该问题。尝试通过手动调试应用程序以及分析应用程序和服务器日志来诊断问题可能来自何处。理想情况下,将整个应用程序的副本复制到本地开发计算机,并执行分步调试过程,这将允许您重新创建发生 406 Not Acceptable 的确切场景,并在错误发生时查看应用程序代码。

无论原因是什么——即使您这次设法修复了它——在您自己的应用程序中出现类似 406 Not Acceptable 的问题,他们发生的时刻都是您可能想要实现错误管理工具的良好指示,它将帮助您自动检测错误并会提醒你。Airbrake 的错误监控软件可为您的所有开发项目提供实时错误监控和自动异常报告。Airbrake 最先进的 Web 仪表板可确保您收到有关应用程序运行状况和错误率的全天候状态更新。无论您从事什么工作,Airbrake 都可以轻松与所有最流行的语言和框架集成。此外,Airbrake 还可以轻松自定义异常参数,同时让您完全控制活动错误滤清系统,因此您只收集最重要的错误。

现在就来看看 Airbrake 的错误监控软件吧,亲自了解为什么这么多世界上最好的工程团队使用 Airbrake 来彻底改变其异常处理实践!