Перезапись динамических URL - PullRequest
7 голосов
/ 09 октября 2011

Я пытаюсь переписать 1 динамический URL-адрес в другой динамический URL следующим образом;

/category?category=News to
/categorysearch/result/?q=news

Мне было интересно, есть ли у кого-нибудь идея, как это можно сделать в htaccess?

Спасибо.

Ответы [ 3 ]

5 голосов
/ 15 октября 2011

Итак, окончательное решение EDITED (для вашего связанного .htaccess):

RewriteCond %{REQUEST_FILENAME} ethical [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)ethical(=|%3D)([^&]+) [NC]
RewriteRule .* /catalogsearch/result/?q=%3 [L,R]

Если я использую термины «категория», как в этом текущем вопросе:

RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)category(=|%3D)([^&]+) [NC]
RewriteRule .* /categorysearch/result/?q=%3 [L,R]

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

# outside of a Directory section
RewriteMap lowercase int:tolower
# in a Directory section (not a .htaccess)
RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} (^|&|%26|%20)category(=|%3D)([^&]+) [NC]
RewriteRule .* /catalogsearch/result/?q=${lowercase:%3} [L,R]

Но, как прокомментировал , этот последний с tolower не мог работать в .htaccess - в любом случае .htaccess плох, действительно, для выступлений, вы должны действительно подумать о настройке AllowOverride None и переместить все это в виртуальном хосте И такие приятные вещи, как rewriteMaps не могут работать с файлами .htaccess.

Так что теперь я объясню правила. Во-первых, основная проблема в вашей ситуации состоит в том, что все, что после "?" , это query_string , а не запрашиваемое имя файла . И большинство rewriteRules пытаются работать с запрошенным именем файла. Итак, я сначала проверяю, что мы находимся на целевом имени файла:

RewriteCond %{REQUEST_FILENAME} category [NC]

Затем мы будем работать над строкой запроса (все после знака вопроса). Мы могли бы написать что-то более простое, как это:

RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} ^category=(.+) [NC]
RewriteRule .* /catalogsearch/result/?q=${lowercase:%1} [L,R]

Чтобы поймать все после? Category = в переменной% 1, доступной для RewriteRule. Но у параметра QUERY_STRING есть несколько проблем, давайте попробуем немного повеселиться с ним:

  • Для этого параметра декодирование URL еще не выполнено
  • категория, возможно, не первый параметр в списке параметров
  • возможно, даже не последний (& foo = bar)
  • у вас может быть несколько пробелов до

EDITED

Мой первый ответ был:

RewriteCond %{REQUEST_FILENAME} category [NC]
RewriteCond %{QUERY_STRING} [^|&|%26|%20][category](=|%3D)([^&]+) [NC]
RewriteRule .* /catalogsearch/result/?q=${lowercase:%2} [L,R]

Если [^|&|%26|%20] уловить тот факт, что это может быть начальный параметр или параметр после & или пробела, %26 является & urlencoded.

Но это было неправильно , благодаря комментарию @mootinator, я проверил немного больше, [категория] соответствует 'категории', но также 'atcatcategory' и любой комбинации букв этих тезисов.

RewriteCond %{QUERY_STRING} category(=|%3D)([^&]+) [NC]

Соответствует аргументу 'category', удаление ^ позволяет разместить этот аргумент в любом месте. Но это также соответствует аргументу с именем subcategory. Поэтому первая буква должна быть пробелом или & (или началом строки запроса).

Это была причина для [^|&|%26|%20], означая для меня начало цепочки ИЛИ или пробела или & в урленкодированном. Но это было также неправильно , ^ внутри [] означает отрицание. Поэтому нам нужно использовать здесь также соответствующие скобки: (^|&|%26|%20), теперь это работает, единственная проблема в том, что значение аргумента теперь% 3, а не% 2

Затем мы ловим слово (категория), чтобы быть точным, мы должны фактически поймать его буква за буквой с заглавной, строчной и urlencoded версией буквы в нижнем и верхнем регистре, что-то вроде ужасного [c|C|%43|%63][a|A|%61|%41][t|T|%74|...]to be continued - и, возможно, я должен использовать скобки вместо скобок, черт возьми, проверьте список символов в кодировке здесь .

(=|%3D) - это символ '=', кодированный или нет. Я мог бы использовать [=|%3D], но %3D не подходит в этом случае, я не понимаю, почему (mod_rewrite - страна странных вещей) . Из-за этой первой подходящей круглой скобки мы должны будем использовать переменную% 2, а не% 1.

И тогда у нас есть хороший ([^&]+), который означает что угодно, но не '&'.

После этих условий мы применяем RewriteRule. Мы берем все (это .*) и перенаправляем его на /catalogsearch/result/?q=%2, где используем %3, а не $1 или $3, так как мы ничего не записываем в rewriteRule, но при условии до (%3) это третья записанная информация о последнем условии, поэтому ([^&]+)). Если вы добавите флаг QSA ([L, R, QSA]) в rewriteRule, вы даже вернете другие параметры в окончательной строке запроса, так что:

ethical?bar=toto& ethical=Foo&zorglub=titi 
=> is redirected to 
catalogsearch/result/?q=foo&bar=toto&%2520ethical=Foo&zorglub=titi

А если я поиграюсь с небольшой кодировкой URL:

ethical?bar=toto%26 ethical%3DFoo&zorglub=titi 
=> is redirected to 
catalogsearch/result/?q=foo&bar=toto%2526%2520ethical%253DFoo&zorglub=titi

Но это не конец игры, я позволю вам разобраться со всеми проблемами урлен-кодирования, которые могут возникнуть, если вы захотите обнаружить все изменения значения Foo и смешать их с tolower (здесь он не работает).Возможно, у вас даже не будет проблем с закодированными URL в ваших параметрах или дополнительных атрибутах, но это было забавно: -)

0 голосов
/ 13 октября 2011

В зависимости от того, что вы пытаетесь сделать, и от того, какие конкретные вещи должны быть, есть два варианта:

Первое - это решение Роба В., которое должно перенаправить пользователя с /category?category=News на * 1004.*

Если, как кажется, ваши URL-адреса чувствительны к регистру, вы можете посмотреть на PHP-скрипт следующим образом:

$matches = array();
if( preg_match( "/^/category\?category=(.+)/", $_SERVER['REQUEST_URI'], $matches ) ) {
    header( 'Location: http://' . $_SERVER['HTTP_HOST'] . '/categorysearch/result/?q= . strtolower($matches[1]) );
}
else {
    //ERROR HANDLING
}

После того, как все решено, вы можете использоватьПравило, подобное следующему, для перенаправления с использованием полностью строчного параметра.

RewriteRule ^category\?category=(.+)$ redirect.php [L]

Вместе это решение перенаправит /category?category=News на /categorysearch/result/?q=news

0 голосов
/ 09 октября 2011

Я думаю

RewriteRule ^/category?category=(.*) /categorysearch/result/?q=news

Сделаем это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...