Исключение пути в WordPress с помощью перенаправлений в .htaccess (Apache)

26 июн. 2019 г., 19:25:03
Просмотры: 6.18K
Голосов: 3

Я хочу исключить путь, соответствующий правилу, из загрузки WordPress. Обычно я решаю это с помощью флага [L] в правиле перед всеми остальными.

Для упрощения примера, предположим, что я хочу сопоставить простой путь /foo/.

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

Однако это не работает. Несколько других вариантов предложены в этом старом посте на Stack Overflow, но ни один из них не работает (ни у меня, ни у кого-либо в комментариях к тому посту).

Я также пробовал это условие перезаписи вместо правила:

RewriteCond %{REQUEST_URI} ^/?(foo/.*)$

А также добавление ErrorDocument 401 default в конец файла .htaccess.

8
Комментарии

Как именно это не работает? WordPress показывает свою страницу с ошибкой 404?

Sally CJ Sally CJ
27 июн. 2019 г. 05:49:07

Да, перенаправление просто не срабатывает, поэтому если страница существует, она переходит на /foo, а если страницы не существует, отображается 404 ошибка темы. По сути, это правило не препятствует маршрутизации WordPress.

Orun Orun
27 июн. 2019 г. 16:26:38

Я тоже получаю ошибку 404, но в моем случае это ожидаемый результат, поскольку путь (/foo) не существует, а перезапись не перенаправляется ни на какие скрипты. Попробуйте отключить плагины и/или использовать стандартную тему? Примечание: я вижу стандартную страницу ошибки, которую выдает Apache, а не WordPress.

Sally CJ Sally CJ
27 июн. 2019 г. 16:35:56

Попробовал отключить все плагины и использовать тему twenty-nineteen (моя тема кастомная в любом случае, и я мало пользуюсь плагинами). Но безрезультатно. Какое именно правило из перечисленных вы используете? RewriteRule ^foo/?$ - [L]? Где именно в последовательности чтения .htaccess вы его разместили?

Orun Orun
27 июн. 2019 г. 20:15:22

Да, именно RewriteRule ^foo/?$ - [L], и я разместил его в том же самом месте, что и в вопросе — после RewriteEngine On. Но этот блок IfModuleединственное содержимое моего файла .htaccess. Может быть, это проблема с кешированием? Попробуйте очистить кеш браузера и сайта, а также попробуйте другой браузер — возможно, это поможет?

Sally CJ Sally CJ
27 июн. 2019 г. 20:42:57

Кеширование тут вряд ли при чем, ведь все это должно обрабатываться на стороне сервера. Но я также попробовал случайное правило, и оно работает, так что правила в .htaccess действительно работают в этом файле. Я попытался удалить все остальное, но безрезультатно. Просто интересно, какую версию Apache вы используете? Можете выполнить apache2 -v или httpd -v?

Orun Orun
27 июн. 2019 г. 21:02:38

Нет, не могу, не на том сервере. Но у меня работает Apache/2.4.26 (Red Hat). И на другом сервере (httpd -v = Apache/2.4.39 (Unix)), правило перезаписи тоже сработало.

Sally CJ Sally CJ
28 июн. 2019 г. 02:33:07

Спасибо за проверку, должно быть что-то в моей конфигурации apache

Orun Orun
28 июн. 2019 г. 15:49:59
Показать остальные 3 комментариев
Все ответы на вопрос 3
0

Вам следует использовать RewriteCond вместо RewriteRule. Используйте это:

RewriteCond %{REQUEST_URI} !/foo/

Таким образом, полный код может выглядеть так:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_URI} !/foo/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
2 июл. 2019 г. 14:01:33
3

Одна небольшая загвоздка заключается в том, что вам нужно обновить RewriteRule ./ в предпоследней строке. Вот обновлённый (и протестированный) фрагмент для вас:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_URI} !^/foo/.*$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ./ /index.php [L]
</IfModule>

# END WordPress

Я протестировал оба варианта:

Надеюсь, это поможет!!

2 июл. 2019 г. 14:10:13
Комментарии

Вот и всё, спасибо. Хотя я не уверен, почему . не соответствует ./, должно было соответствовать обоим. Для тех, у кого возникнет эта проблема в будущем: я немного оптимизировал, изменив на ./? и написал небольшой сервис для проверки файла .htaccess, чтобы убедиться, что некоторые плагины или обновления не перезаписали/сбросили его.

Orun Orun
2 июл. 2019 г. 21:07:28

@Orun не очень хорошая идея настраивать сервис, который запрещает изменение файла. Вместо этого следует отслеживать только ту часть, потому что многие полезные плагины записывают другие блоки, которые не должны быть запрещены.

T.Todua T.Todua
4 июл. 2019 г. 20:01:33

Да, согласен. Файл по-прежнему полностью доступен для записи. На самом деле у меня уже был сервис, который записывает мой собственный блок в .htaccess внутри моей темы, так что я просто расширил его. Он ищет определённую строку, изменяет её при выполнении условия и затем записывает изменение в специальный лог.

Orun Orun
5 июл. 2019 г. 17:21:46
2

Следующее правило работает для меня:

RewriteRule ^(foo)($|/) - [L]

Это означает, что любой путь, начинающийся с foo, например /foo/, /foo/bar/ или что-то подобное, приводит к Apache 404 вместо темы 404; при условии, что фактического каталога с таким путем не существует.

Правило должно быть перед последней стандартной строкой блока WordPress:

RewriteRule . /index.php [L]

И не имеет значения, если оно находится после RewriteBase /, оно может быть и до него; ранее это было просто поспешно и небрежно сформулировано с моей стороны.

Это даст вам возможность оставить блок между # BEGIN WordPress и # END WordPress нетронутым, если вы хотите. Поместив

<IfModule mod_rewrite.c>
RewriteRule ^(foo)($|/) - [L]
</IfModule>

перед # BEGIN WordPress.

Возможно, вы захотите предотвратить создание пути /foo/ в WordPress, вот что пришло на ум:

add_filter( 'wp_unique_post_slug', 'no_more_foo_wp_unique_post_slug', 2, 6 );
function no_more_foo_wp_unique_post_slug( 
  $slug, $post_ID, $post_status, $post_type, $post_parent, $original_slug 
) {
  if ( $post_parent === 0 ) {
    $pattern = '/^foo$/';
    $replace = 'bar';
    $slug   = preg_replace( $pattern, $replace, $slug );
  }
  return $slug;
}
2 июл. 2019 г. 15:11:38
Комментарии

Вы правы, что я должен был установить своё правило после базового, не уверен, почему я сделал это до в этом посте! На самом деле в рабочем .htaccess оно было установлено после. Спасибо, что обратили внимание. Это была моя ошибка при редактировании markdown здесь.

Orun Orun
5 июл. 2019 г. 17:23:45

@Orun Я немного уточнил свой ответ.

Nicolai Grossherr Nicolai Grossherr
5 июл. 2019 г. 19:58:45