Apache htaccess несколько условий перезаписи для нескольких правил

Я взял на себя веб-сайт и заметил, что предыдущий разработчик имел несколько .htaccess переписать правила, это короткий пример:

RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$
RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteRule ^(.*)/landing/(.*)/(.*)$ landing.php?page=$1&id=$2&mid=$3
RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$
RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteRule ^(.*)/landing/(.*)$ landing.php?page=$1&id=$2
RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$
RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteRule ^(.*)/landing$ landing.php?page=$1

Условие перезаписи всегда одинаково для всех правил. Есть ли способ объединить правила перезаписи, чтобы условия были записаны только один раз?

Я посмотрел на пропускающий флаг, но он не имеет обратной ссылки. Насколько я вижу, мне не нужны обратные ссылки с этими условиями, однако, является ли пропустить лучший подход? Или есть лучшая практика, как этого добиться? (Кто-то предложил мне использовать флаг QSA, однако после исследования я не думаю, что это имеет какое-либо отношение к тому, чего я хочу достичь.)

2 ответа

Решение
RewriteCond %{REQUEST_URI} !^/[0-9]+\..+\.cpaneldcv$
RewriteCond %{REQUEST_URI} !^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$
RewriteCond %{REQUEST_URI} !^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$

Этот грязный блок условий вводится автоматически cPanel перед каждым RewriteRule директива при автоматическом обновлении сертификата безопасности SSL (Let's Encrypt?). Эти условия обеспечивают доступность файла проверки (необходимого для обновления сертификата SSL).

К сожалению, я не смог понять, почему cPanel делает это таким образом - это может быть кошмаром обслуживания, и я столкнулся с директивами, которые были нарушены этими условиями (по общему признанию, директивы были не идеальны с самого начала). (Я пытался спрашивать на форумах cPanel, но у меня никогда не было хорошего ответа.)

... есть ли способ объединить правила перезаписи, чтобы условия были записаны только один раз?

Да. Вы можете переместить эти условия в свой блок в начале .htaccess файл и обратить их значение, так что вместо того, чтобы вызвать RewriteRule когда запрос не соответствует шаблону (используя отрицательное регулярное выражение). Вы можете предотвратить дальнейшие перезаписи, когда запрос соответствует шаблону. Например:

# BEGIN cPanel SSL CERT RENEWAL
RewriteCond %{REQUEST_URI} ^/[0-9]+\..+\.cpaneldcv$ [OR]
RewriteCond %{REQUEST_URI} ^/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$ [OR]
RewriteCond %{REQUEST_URI} ^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ [OR]
RewriteCond %{REQUEST_URI} ^/\.well-known/pki-validation/[A-F0-9]{32}\.txt(?:\ Comodo\ DCV)?$
RewriteRule ^ - [L]
# END cPanel SSL CERT RENEWAL

Обратите внимание на удаление ! (отрицание) префикс на CondPattern и дополнительный OR флаг на первых трех условиях. RewriteRule затем предотвращает дальнейшую обработку директив mod_rewrite, если запрос совпадает.

(На Apache 2.4.8+ эти директивы могут быть полностью перенесены в конфигурацию сервера. С помощью RewriteOptions InheritDownBefore.)

Затем следуют только RewriteRule директивы у вас были раньше (хотя я добавил L флаг):

RewriteRule ^(.*)/landing/(.*)/(.*)$ landing.php?page=$1&id=$2&mid=$3 [L]
RewriteRule ^(.*)/landing/(.*)$ landing.php?page=$1&id=$2 [L]
RewriteRule ^(.*)/landing$ landing.php?page=$1 [L]

Вы, вероятно, должны быть в том числе L флаги на тех оставшихся переписывает.

Вы также можете объединить эти 3 переписки в одну директиву, если хотите, но это будет зависеть от того, будет ли ваше приложение обрабатывать пустые параметры URL.

(Кто-то предложил мне использовать флаг QSA, однако после исследования я не думаю, что это имеет какое-либо отношение к тому, чего я хочу достичь.)

Да, это не имеет ничего общего с этой конкретной проблемой. QSA Флаг (Query String Append) позволит вам объединить любую строку запроса, которая присутствует в запросе, со строкой запроса, которую вы пишете в RewriteRule замена.

Проблема:

Например, у вас есть такие условия и правила:

      RewriteCond %{REQUEST_URI} ^(...COND_1...)$
RewriteCond %{REQUEST_URI} ^(...COND_2...)$
RewriteRule ^(...RULE_1_FROM...)$ (...RULE_1_TO...)

RewriteCond %{REQUEST_URI} ^(...COND_1...)$
RewriteCond %{REQUEST_URI} ^(...COND_2...)$
RewriteRule ^(...RULE_2_FROM...)$ (...RULE_2_TO...)

RewriteRule ^(...RULE_3_FROM...)$ (...RULE_3_TO...)

Условия №1 и №2 одинаковы, и вам необходимо применить правила №1 и №2 в этих условиях. Правило №3 не зависит от условий №1 и №2 и должно быть отделено от этих условий.

Решение:

Если вы не хотите повторять условие №1 и условие №2 каждый раз для каждого правила, вам следует внести 2 изменения:

Изменение 1. Создайте противоположные условия из №1 и №2:

      RewriteCond %{REQUEST_URI} !^(...COND_1...)$ [OR]
RewriteCond %{REQUEST_URI} !^(...COND_2...)$

(Я добавил!песок[OR]здесь).

Изменение 2. У вас есть 2 правила, связанных с этими условиями, поэтому добавьте эту строку после всех условий:RewriteRule ^ - [S=2]. Цифра в квадратных скобках — это ряд правил , которые необходимо применять в данных условиях. Если у вас есть 3 строки правил, вы должны написатьRewriteRule ^ - [S=3]и так далее.

Вот полный код:

      RewriteCond %{REQUEST_URI} !^(...COND_1...)$ [OR]
RewriteCond %{REQUEST_URI} !^(...COND_2...)$
RewriteRule ^ - [S=2]
RewriteRule ^(...RULE_1_FROM...)$ (...RULE_1_TO...)
RewriteRule ^(...RULE_2_FROM...)$ (...RULE_2_TO...)

RewriteRule ^(...RULE_3_FROM...)$ (...RULE_3_TO...)
Другие вопросы по тегам