#apache #.htaccess #mod-rewrite #url-rewriting
#apache #.htaccess #мод-переписать #url-переписывание
Вопрос:
Мне нужно переписать каталог на основе URL:
https://example.com/subdir/gulp-service/category?parent=666amp;name=test
для строки запроса:
?service=gulp-serviceamp;file=categoryamp;query_string=parent=666amp;name=test
.htaccess
должно работать https://example.com/subdir/
.
Как написать такой .htaccess ?
Я хочу, чтобы работали 2 URL-адреса:
https://example.com/subdir/gulp-service
и
https://example.com/subdir/gulp-service/category?parent=666amp;name=test
Я написал для службы и файла:
RewriteEngine On
RewriteRule ^([a-z0-9-] )$ ?service=$1
RewriteRule ^([a-z0-9-] )/([a-z] )$ ?service=$1amp;file=$2
в PHP после print_r($_GET)
того, как я:
Array
(
[service] => mskip-service
[file] => category
)
Как добавить недостающую часть URL-адреса в строку запроса?
Комментарии:
1. Спасибо, что поделились своими усилиями, значит, вы нажали ссылку group.com/subdir/gulp-service/category?parent=666amp;name=test в браузере? Что должно обслуживаться по какой ссылке? Не могли бы вы подробнее рассказать об этом?
2. Какова цель URL-пути? В вашем примере похоже, что это корень документа? Или, возможно, он должен перезаписать тот же URL-путь?
?service=gulp-serviceamp;file=categoryamp;query_string=parent=666amp;name=test
— Хотя это выглядит неправильно, поскольку это приведет кquery_string
/parent=666
иname
/test
, что не выглядит так, как будто это намерение? Предположительноquery_string
, параметр URL должен содержать всю строку запроса из первоначального запроса? В этом случае он должен быть %-закодирован как?service=gulp-serviceamp;file=categoryamp;query_string=parent=666&name=test
. (?)3. Да, конечно, это может быть URL-адрес в кодировке, но как это сделать, чтобы добавить его в строку запроса?
4. Предположительно
666
, иtest
вparent=666amp;name=test
являются переменными? Значениеparent
всегда числовое? Всегда ли параметры URL (если они вообще присутствуют)parent=<number>amp;name=<something>
, или это само по себе может быть переменным? Ваши директивы подразумевают, что сегментgulp-service
пути и сегментcategory
пути также являются переменными?
Ответ №1:
Предположительно, вам требуется следующее в вашем результирующем $_GET
массиве, учитывая ваш второй пример URL:
Array
(
[service] => mskip-service
[file] => category
[query_string] => parent=666amp;name=test
)
Если исходная строка запроса является полностью переменной, то это немного сложно, поскольку это означает, что исходная строка запроса должна быть полностью закодирована в URL (как значение параметра URL), прежде чем присваиваться параметру query_string
URL.
В противном случае вы получите следующий (нежелательный / искаженный) вывод * 1:
Array
(
[service] => mskip-service
[file] => category
[query_string] => parent=666
[name] => test
)
Итак, вместо следующего (как в вашем примере):
?service=gulp-serviceamp;file=categoryamp;query_string=parent=666amp;name=test
Это должен быть URL-адрес, закодированный таким образом в конечной цели:
?service=gulp-serviceamp;file=categoryamp;query_string=parent=666&name=test
Для этого нет встроенного метода ( escape()
функция в выражениях Apache не кодирует =
и amp;
— два символа, которые нам нужно кодировать!). Однако мы можем эффективно искать / заменять эти символы в строке запроса с помощью внутреннего рекурсивного цикла, прежде чем переписывать конечный запрос.
Я бы также рассмотрел возможность объединения двух правил в одно. Итак, оба ваших примера обрабатываются одним правилом. Единственное предостережение при этом заключается в том, что в первом примере вы получаете пустой file
параметр URL. И вы всегда будете получать query_string
параметр URL, который может быть пустым, если в первоначальном запросе нет строки запроса.
Вместо этого попробуйте следующее:
# Manually encode "=" in query string with search/replace
RewriteCond %{QUERY_STRING} (. )=(. )
RewriteRule ^[a-z0-9-] (/[a-z] )?$ $0?%1=%2 [N=20]
# Manually encode "amp;" in query string with search/replace
RewriteCond %{QUERY_STRING} (. )amp;(. )
RewriteRule ^[a-z0-9-] (/[a-z] )?$ $0?%1&%2 [N=20]
# Finally rewrite to desired URL-path
RewriteRule ^([a-z0-9-] )(?:/([a-z] ))?$ ?service=$1amp;file=$2amp;query_string=%{QUERY_STRING} [L]
Обратите внимание, что %
символы, являющиеся частью последовательности, закодированной в %, должны быть экранированы обратной косой чертой в строке подстановки, чтобы избежать конфликта с %N
обратными ссылками.
N
Флаг заставляет механизм перезаписи немедленно запускаться заново, используя текущий результат в качестве входных данных. Значение здесь указывает максимальное количество циклов, которые будут выполняться (требуется Apache 2.4.8).
К моменту обработки 3-го правила, которое выполняет требуемую перезапись, исходная строка запроса (т.е. значение QUERY_STRING
переменной сервера) уже имело все экземпляры =
и amp;
заменено на =
и &
соответственно.
ОБНОВЛЕНИЕ: * 1 Однако, если «искаженный» вывод (как упоминалось выше) «ОК», тогда решение проще. Вам просто нужно 3-е правило сверху:
# Append the original query string (unencoded)
RewriteRule ^([a-z0-9-] )(?:/([a-z] ))?$ ?service=$1amp;file=$2amp;query_string=%{QUERY_STRING} [L]
Затем вы получите вывод:
Array
(
[service] => mskip-service
[file] => category
[query_string] => parent=666
[name] => test
)
Однако в этом случае на самом деле не было бы никакой необходимости в дополнительном query_string
параметре URL (который, возможно, все равно сломан). Вы можете просто объединить (добавить) исходную строку запроса и вручную извлечь необходимые значения. Например:
# Merge the original query string
RewriteRule ^([a-z0-9-] )(?:/([a-z] ))?$ ?service=$1amp;file=$2 [QSA,L]
QSA
Флаг добавляет (объединяет) исходную строку запроса.
Для получения следующего вывода, учитывая пример URL:
Array
(
[service] => mskip-service
[file] => category
[parent] => 666
[name] => test
)
Если вы удалите элементы «service» и «file» из массива, вы сможете восстановить исходную строку запроса из оставшихся пар имя / значение.
(Хотя это может зависеть от того, что серверный скрипт ожидает в качестве входных данных.)