Назад | Перейти на главную страницу

Ошибка Apache2 mod_rewrite для несуществующих подкаталогов

Еще более короткая версия моего файла .htaccess (последнего RewriteCond там не было) отлично работает на моем общем веб-хостинге, но я перешел на VPS с Ubuntu 12 со стандартным Apache2, но он просто не будет работать (даже с моими изменениями), и я не могу понять почему. Я могу получить доступ к example.com или example.com/news, но не к example.com/article/4

Я поместил блок mod_rewrite из .htaccess в конфигурацию vhost наоборот, но это, похоже, не сработало. Я предполагаю, что он на самом деле пытается перейти в подкаталог статьи или что-то в этом роде (которого не существует, так что 404), но я не могу понять, как остановить его от этого.

Я использую Apache версии 2.2.22

Мой файл виртуального хоста

<VirtualHost 127.0.0.1:80>
DocumentRoot /home/example/www/example.com
RewriteLogLevel 3
RewriteLog /home/example/www/example.rewrite.log
<Directory "/home/example/www/example.com">
AllowOverride All
Options -ExecCGI +FollowSymLinks -Indexes -MultiViews
Order deny,allow
allow from all
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteOptions inherit
</IfModule>
</Directory>
AccessFileName .htaccess
ServerSignature Off
ServerName example.com
ErrorLog /home/example/www/example.log
LogLevel warn
</VirtualHost>

Мой файл .htaccess

ErrorDocument 404 /index.php?404
ErrorDocument 403 /index.php?403
ErrorDocument 500 /index.php?500

Options -ExecCGI +FollowSymLinks -Indexes -MultiViews

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteOptions inherit

    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-s
    RewriteCond %{REQUEST_FILENAME} !-l
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_URI} !^/index\.php
    RewriteRule ^(.*)$ /index.php?$1 [L]
</IfModule>

Переписать журнал цикла перенаправления при доступе к example.com/article/4

[example.com/sid#8475130][rid#867d470/initial] (3) [perdir /home/example/www/example.com/] add path info postfix: /home/example/www/example.com/article -> /home/example/www/example.com/article/4
[example.com/sid#8475130][rid#867d470/initial] (3) [perdir /home/example/www/example.com/] strip per-dir prefix: /home/example/www/example.com/article/4 -> article/4
[example.com/sid#8475130][rid#867d470/initial] (3) [perdir /home/example/www/example.com/] applying pattern '^(.*)$' to uri 'article/4'
[example.com/sid#8475130][rid#867d470/initial] (2) [perdir /home/example/www/example.com/] rewrite 'article/4' -> '/index.php?article/4'
[example.com/sid#8475130][rid#867d470/initial] (3) split uri=/index.php?article/4 -> uri=/index.php, args=article/4
[example.com/sid#8475130][rid#867d470/initial] (2) [perdir /home/example/www/example.com/] trying to replace prefix /home/example/www/example.com/ with /
[example.com/sid#8475130][rid#867d470/initial] (1) [perdir /home/example/www/example.com/] internal redirect with /index.php [INTERNAL REDIRECT]
[example.com/sid#8475130][rid#b6ce9950/initial/redir#1] (3) [perdir /home/example/www/example.com/] strip per-dir prefix: /home/example/www/example.com/index.php -> index.php
[example.com/sid#8475130][rid#b6ce9950/initial/redir#1] (3) [perdir /home/example/www/example.com/] applying pattern '^(.*)$' to uri 'index.php'
[example.com/sid#8475130][rid#b6ce9950/initial/redir#1] (1) [perdir /home/example/www/example.com/] pass through /home/example/www/example.com/index.php
[example.com/sid#8475130][rid#b6cd7058/initial] (3) [perdir /home/example/www/example.com/] strip per-dir prefix: /home/example/www/example.com/404 -> 404
[example.com/sid#8475130][rid#b6cd7058/initial] (3) [perdir /home/example/www/example.com/] applying pattern '^(.*)$' to uri '404'
[example.com/sid#8475130][rid#b6cd7058/initial] (2) [perdir /home/example/www/example.com/] rewrite '404' -> '/index.php?404'
[example.com/sid#8475130][rid#b6cd7058/initial] (3) split uri=/index.php?404 -> uri=/index.php, args=404
[example.com/sid#8475130][rid#b6cd7058/initial] (2) [perdir /home/example/www/example.com/] trying to replace prefix /home/example/www/example.com/ with /
[example.com/sid#8475130][rid#b6cd7058/initial] (1) [perdir /home/example/www/example.com/] internal redirect with /index.php [INTERNAL REDIRECT]
[example.com/sid#8475130][rid#b6ce5440/initial/redir#1] (3) [perdir /home/example/www/example.com/] strip per-dir prefix: /home/example/www/example.com/index.php -> index.php
[example.com/sid#8475130][rid#b6ce5440/initial/redir#1] (3) [perdir /home/example/www/example.com/] applying pattern '^(.*)$' to uri 'index.php'
[example.com/sid#8475130][rid#b6ce5440/initial/redir#1] (1) [perdir /home/example/www/example.com/] pass through /home/example/www/example.com/index.php

Обобщенный журнал доступа

"GET /article/4 HTTP/1.1" 302 4095 "-"
"GET /404 HTTP/1.1" 200 2405 "-"

Журналы показывают, что ваши правила работают идеально.

В index.php скрипт был выполнен с аргументами ?article/4 и сценарий ответил перенаправлением 302 на /404. Здесь нет [R] в любом из этих правил перезаписи, поэтому перенаправление должен быть выполнен скриптом.

Браузер сделал дополнительный запрос для /404 и было получено 200 ответов.


Подозреваю, у вас три проблемы. Во-первых, ваш скрипт выдает ответ 302 на URL-адрес. /404 когда он не может найти контент. Это должен выдать ответ 404.

Во-вторых, ваш /404 сценарий выдает ответ 200. Это должен выдать ответ 404.

В-третьих, ваш скрипт index.php не знает, как обращаться с аргументом ?article/4. Я не знаю, как работает ваш скрипт, но я бы посоветовал немного отладить сам скрипт, чтобы решить вашу проблему. Использовать echo() на некоторых переменных на разных этапах сценария или что-то вроде file_put_contents("/var/log/apache2/example.com.debug.log", time()." ".$variable."\n", FILE_APPEND).

Ваши исходные правила перезаписи кажутся достаточно простыми:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteOptions inherit

    RewriteBase /
    RewriteCond %{REQUEST_FILENAME} !-s
    RewriteCond %{REQUEST_FILENAME} !-l
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_URI} !^/index\.php
    RewriteRule ^(.*)$ /index.php?$1 [L]
</IfModule>

Вы пробовали использовать простой SEO / SEF .htaccess например, тот, который идет в комплекте с WordPress? Вот он, но я добавил RewriteOptions inherit правило из исходной настройки:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteOptions inherit

    RewriteBase /
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]
</IfModule>