RewriteMap внутри RewriteCond не работает (Apache)

. У меня есть RewriteCond , который проверяет, содержит ли {QUERY_STRING} правильный номер версии, если он не перенаправляет пользователей на правильную версию.

Например, если v0.7 является последней, пользователи, обращающиеся к http: // localhost /? v = 0.5 , должны быть перенаправлены на http : // localhost /? v = 0.7 но по какой-то причине, если я использую RewriteMap в условиях, это не работает ...

Это работает

RewriteMap versions txt:/var/www/html/version.txt
RewriteCond "%{QUERY_STRING}" !^v=0.7
RewriteRule "^/$" "/?v=${versions:version}" [R,L]

Это не ' t

RewriteMap versions txt:/var/www/html/version.txt
RewriteCond "%{QUERY_STRING}" !^v=${versions:version}
RewriteRule "^/$" "/?v=${versions:version}" [R,L]

Содержимое version.txt

##
##  version.txt -- rewriting map
##  The version number written here will be mapped to the URL
##
##
version 0.7
2
задан 29 September 2020 в 08:01
1 ответ
RewriteCond "%{QUERY_STRING}" !^v=${versions:version}

Это не работает, потому что ] CondPattern(2-й аргумент директивы RewriteCond)является регулярным выражением и, следовательно, не поддерживает раскрытие переменных. (Так же, как вы не можете использовать обратные ссылки в форме $nили %n, или серверные переменные %(SERVER_VAR}, или env vars %{ENV:MY_ENV_VAR}и т. д. )В противном случае это будет конфликтовать с синтаксисом регулярных выражений PCRE. Только первый аргумент TestString(директивы RewriteCond)и аргументыRewriteRuleподстановки поддерживают раскрытие переменных, поскольку эти аргументы являются «обычными» строками, а не регулярными выражениями.

Тем не менее, вы все равно можете сделать то, что вам нужно, и проверить, что правильный номер версии, возвращенный из RewriteMap, присутствует в начале строки запроса. Вместо этого расширьте результат RewriteMapв TestString (, который поддерживает раскрытие переменных, поскольку это «обычная» строка, а не регулярное выражение )и , сравните это с использованием внутренняя обратная ссылка.

Например, замените RewriteCondна:

RewriteCond %{QUERY_STRING}@${versions:version} !^v=([\d.]+)(?:&[^@]*)?@\1

После раскрытия переменной мы получим соответствие строки вида v=0.5@0.7регулярному выражению ^v=([\d.]+)(?:&.*)?@\1. \1является внутренней обратной ссылкой на первый захваченный подшаблон (, т.е. значение параметра URL v). Таким образом, это эффективно сопоставляет значение параметра URL со значением, возвращаемым из RewriteMap. Все это выражение затем инвертируется(!префиксом), поэтому оно считается успешным, когда условие не соответствует, т.е. номер версии другой.

([\d.]+)-Соответствует номеру версии в строке запроса, состоящей из 1 или более цифр или буквенных точек.например.0.5

(?:&.*)?-Соответствует остатку строки запроса (, если есть).

@— это просто произвольная строка, которая иначе не встречается в строке запроса или строке «версия».

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

2
ответ дан 29 September 2020 в 11:37

Теги

Похожие вопросы