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 не индексируют URL, возвращающий статус 406 Not Acceptable. Ранее проиндексированные 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. Расширьте список принимаемых медиатипов. Например, добавьте application/json рядом с text/html или используйте /, чтобы принимать любой формат. Посмотрите точное значение заголовка Accept, отправляемого клиентом, в DevTools браузера (вкладка Network) или через curl -v.
Проверьте ограничения Accept-Language. Запрос языка, который сервер не поддерживает, вызывает эту ошибку. Расширьте список языков или добавьте запасной вариант с подстановочным знаком (*). Этим заголовком автоматически управляют языковые настройки браузера. Измените их в языковых предпочтениях браузера.
Уберите излишне строгие значения Accept-Encoding или Accept-Charset. Узкие требования к кодировке или набору символов ограничивают возможности сервера. Разрешите распространённые значения, такие как gzip, deflate и UTF-8.
Изучите тело ответа на предмет доступных альтернатив. Сервер часто перечисляет поддерживаемые представления в ответе 406. Выберите одно из них и скорректируйте заголовки согласования.
Проверьте конфигурацию согласования содержимого на сервере. Неверно настроенные карты типов или незарегистрированные MIME-типы на сервере приводят к неожиданным ответам 406. В Apache картами типов управляют mod_negotiation и MultiViews. Убедитесь, что директивы AddType регистрируют нужные MIME-типы.
Проверьте правила mod_security или WAF. mod_security в Apache (и подобные WAF) перехватывает запросы и возвращает 406 при срабатывании правила на содержимое запроса, а не на заголовок Accept. Посмотрите в журнале ошибок сервера запись ModSecurity и отметьте идентификатор правила (например, [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