RewriteCond в .htaccess с отрицательным условием регулярного выражения не работает?

Я пытаюсь предотвратить, в этом случае WordPress, переписывание определенных URL-адресов. В этом случае я пытаюсь помешать ему когда-либо обрабатывать запрос в каталоге uploads и вместо этого оставлять его на странице сервера 404. Поэтому я предполагаю, что это просто, как добавление правила:

RewriteCond %{REQUEST_URI} !^/wp-content/uploads/

Это правило должно оцениваться как ложное и заставить цепочку правил терпеть неудачу для этих запросов, тем самым останавливая переписывание. Но нет... Возможно, мне нужно сопоставить обложку полной строки в моем выражении?

RewriteCond %{REQUEST_URI} !^/wp-content/uploads/.*$

Нет, это тоже не так. Поэтому, почесывая голову, я делаю проверку здравомыслия. Возможно, что-то не так с фактическим рисунком. Поэтому я делаю простой тестовый пример.

RewriteCond %{REQUEST_URI} ^/xyz/$

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

RewriteCond %{REQUEST_URI} !^/xyz/$

Теперь я ожидаю увидеть полную противоположность вышеуказанному условию. Переписывание не должно происходить для /xyz/, но для всех других возможных URL-адресов. Вместо этого переписывание происходит для каждого URL-адреса, как /xyz/, так и других.

Итак, либо использование отрицаемых регулярных выражений в RewriteConds нарушено в Apache, либо есть что-то фундаментальное, о котором я не понимаю. Кто из них?

Сервер Apache2.

Файл целиком:

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteBase /
RewriteRule ^index\.php$ - [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/wp-content/uploads/
RewriteRule . /index.php [L]
</IfModule>

Файл по умолчанию WordPress плюс мое правило.

Ответы

Ответ 1

Итак, после большого раздражения, я понял проблему, вроде. Как оказалось, правило в моем первоначальном вопросе фактически делало именно то, что предполагалось. Так было сделано несколько других способов сделать то же самое, например

RewriteRule ^wp-content/uploads/.*$ - [L]

(Отметьте правило как последнее, если шаблон совпадает) или

RewriteRule ^wp-content/uploads/.*$ - [S=1]

(Пропустите следующее правило, если шаблон совпадает), а также отрицательное правило в вопросе, как уже упоминалось. Все эти правила работали очень хорошо и вернули управление Apache без перезаписи.

Проблема возникла после обработки этих правил. Вместо этого проблема заключалась в том, что я удалил стандартные шаблоны 404.shtml, 403.shtml и т.д., Которые предоставил мой хост. Если у вас нет каких-либо перезаписей .htaccess, это работает нормально; сервер будет готовить свою собственную страницу 404 по умолчанию, и все будет работать. (По крайней мере, это то, что я думал, но на самом деле это была двойная ошибка ". Кроме того, при попытке использовать ErrorDocument для обработки запроса была обнаружена ошибка 404 Not Found." )

Когда у вас есть .htaccess, с другой стороны, он выполняется второй раз для страницы 404. Если страница есть, она будет использоваться, но теперь запрос 404.shtml был пойман с помощью правила catch-all и переписан на index.php. По этой причине все другие предложения, которые я получил здесь или в другом месте, потерпели неудачу, потому что в итоге страница 404 была переписана index.php.

Итак, решение было просто восстановить шаблоны ошибок. Оглядываясь назад, было довольно глупо удалять их, но у меня этот менталитет "начать с нуля". Не хочу, чтобы что-то казалось ненужным. По крайней мере, сейчас я понимаю, что происходит, чего я хотел.

Наконец, комментарий к Сесилу: я никогда не хотел запрещать доступ ко всему, просто прекратите переписывать. Не то, чтобы это имело значение сейчас, но я просто хотел прояснить это.

Ответ 2

<IfModule mod_rewrite.c>
RewriteEngine On

RewriteBase /
RewriteRule ^index\.php$ - [L]

RewriteCond %{REQUEST_URI} !^/wp-content/uploads/ [OR]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule . /index.php [L]
</IfModule>

Ответ 3

Если /wp-content/uploads/ действительно является префиксом запрошенного пути URI, ваше правило должно работать как ожидалось.

Но поскольку он, очевидно, не работает, попробуйте не сопоставлять префикс пути полного пути URI, а только оставшийся путь без контекстного префикса пути для каждого каталога, в случае файла .htaccess в корневой директории документа URI путь без ведущего /:

RewriteCond $0 !^wp-content/uploads/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .+ /index.php [L]

Если это не работает, это, безусловно, поможет получить представление о процессе перезаписи mod_rewrites, используя функцию ведения журнала. Поэтому установите RewriteLogLevel на уровень не менее 4, сделайте свой запрос и взгляните на записи в файле журнала, указанные в RewriteLog. Там вы можете увидеть, как mod_rewrite обрабатывает ваш запрос, а с помощью RewriteLogLevel больше или равно 4 вы также увидите значения переменных типа %{REQUEST_URI}.