LoginSignup
3
1

【メモ】Apacheの「406 Not Acceptable」のエラーについて

Last updated at Posted at 2024-03-13

 Apacheの「406 Not Acceptable」のエラーについて。
 このエラーは情報が少なく、遭遇して調べたいときにど忘れしていると調べる事に時間がかかって困るので備忘録的なメモです。

目次

1.406エラーとは
2.406エラーが発生する条件
3.他に406になる状況
4.406を回避しつつ拡張子無しで実行したい場合

406エラーとは

 リクエストを受けたサーバーがコンテンツネゴシエーションをうまく行えず、どのコンテンツを処理するかがURIから判断できなかった時に発生。

406エラーが発生する条件

 ApacheのOptionsの値を変えてphpやhtmlを拡張子無しで実行できる設定にすると、コンテンツネゴシエーションのエラーが出る様になります。
 .httacessを使う設定とは別の方です。

●再現方法
1.Apacheの設定のOptionsMultiViewsを追加し、リクエストに対して扱うメディア種類の判断を自動で行うようにする

Options Indexes FollowSymLinks MultiViews

2.Apacheの設定のAddTypeでメディア種別と実際に扱うファイル拡張子を紐づける
(これで拡張子を省略したURLで動くようになる)

AddType text/html .php

3.AddTypeの設定を無視したMIMEタイプをHTTPヘッダのAcceptに設定し、拡張子を省略したURLで上記の設定をしたサーバーにリクエストをする

curl -i -H 'Content-Type: html/text' -H 'Accept: application/zip' 'http://localhost/php_index'

4.コンテンツネゴシエーションのエラーになる
※この時、リクエストはApacheで止められてURLで指定したファイルは実行されない

HTTP/1.1 406 Not Acceptable
Date: Mon, 11 Mar 2024 04:06:30 GMT
Server: Apache/2.4.58 (Fedora Linux)
Alternates: {"php_index.php" 1 {type text/html}}
Vary: negotiate
TCN: list
Content-Length: 350
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>406 Not Acceptable</title>
</head><body>
<h1>Not Acceptable</h1>
<p>An appropriate representation of the requested resource could not be found on this server.</p>
Available variants:
<ul>
<li><a href="php_index.php">php_index.php</a> , type text/html</li>
</ul>
</body></html>

 だいたい上記の設定とリクエストの組み合わせで発生します。
 そのため、406エラーが発生した時は発生したリクエストのhttpヘッダの内容とURL、そしてApacheの設定を確認する流れになります。

他に406になる状況

 ModSecurityというオープンソースのファイアウォールを導入している場合も、設定ルールに反するリクエストで発生することがある様です。
(ModSecurityはあまり詳しくないので省略…)

406を回避しつつ拡張子無しで実行したい場合

 どうしても拡張子無しでApacheに処理させたい場合は.htaccessが有効です。
 ただし、この方法は複雑な事をしたい場合RewriteRuleの書き方を工夫する必要があり、複雑になりがちです。
 また、すでにApacheのOptionsMultiViewsが設定されていたら干渉するのでApacheの設定からMultiViewsを削除する必要があります。

htaccessの例

●一番シンプルなもの

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [L]

/xxxxx/xxxxx.phpに置き換えます。

/で区切った値をパラメータとして受け取りたい場合

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^\/]*)/?(.*)? $1.php [L]

 /xxxxxまたは/xxxxx//xxxxx.phpに置き換えつつ以降のパスは捨てます。
 捨てた部分はリクエストパラメータとは別で取得します。
 サーバーにURI情報が残るので、例えば、PHPなら$_SERVER['REQUEST_URI']或いはfilter_input(INPUT_SERVER, 'REQUEST_URI')で取得してパラメータとして利用します。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1