406 Not Acceptable
使い方
406 Not Acceptable エラーが届く場合、このレスポンスは Accept や Accept-Language といったネゴシエーション関連のヘッダーによって引き起こされます。クライアントがこれらのヘッダーを1つ以上含めた場合、サーバーは可能な限りその要件を満たします。
最も一般的な 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 を追加するか、どの形式でも受け入れるために / を使います。クライアントが送信している正確な Accept ヘッダーを調べるには、ブラウザの DevTools(Network タブ)または curl -v を使います。
Accept-Language の制約を確認します。サーバーがサポートしていない言語を要求するとこのエラーが発生します。言語の一覧を広げるか、ワイルドカード(*)のフォールバックを追加します。ブラウザの言語設定がこのヘッダーを自動的に制御します。ブラウザの言語設定で調整してください。
過度に制限的な Accept-Encoding や Accept-Charset の値を取り除きます。狭いエンコーディングや文字セットの要求は、サーバーの選択肢を制限します。gzip、deflate、UTF-8 といった一般的な値を許容してください。
レスポンスボディで利用可能な代替案を調べます。サーバーは 406 レスポンスでサポートする表現を列挙していることがよくあります。1つを選び、それに応じてネゴシエーションのヘッダーを調整します。
サーバー側のコンテントネゴシエーション設定を確認します。サーバー上の type map の設定ミスや MIME タイプ登録の欠落が、予期しない 406 レスポンスを引き起こします。Apache では、mod_negotiation と MultiViews が type map を制御します。AddType ディレクティブが必要な MIME タイプを登録していることを検証します。
mod_security や WAF のルールを確認します。Apache の mod_security(および類似の WAF)はリクエストを傍受し、Accept ヘッダーではなくリクエストの内容にルールが反応すると 406 を返します。サーバーのエラーログで ModSecurity のエントリを確認し、ルール ID(例:[id “941160”])を控えます。WAF 全体を無効化するのではなく、その特定のルールを許可リストに入れます。
SecRuleRemoveById 941160
この除外設定は仮想ホストの設定または .htaccess ファイルに置きます。
最小限のリクエストでテストします。すべてのネゴシエーションヘッダーを取り除き、curl で素のリクエストを送って、サーバーがデフォルトの表現を返すかどうかを判断します。素のリクエストが成功する場合は、どのヘッダーが拒否を引き起こしているかを切り分けるため、ネゴシエーションヘッダーを1つずつ戻していきます。
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