Задача: используя IIS URL Rewrite, перенаправить всё содержимое старого каталога (clients) в новое место (customers). Например, /clients/Gazprom/ в /customers/.
Это просто:
<rule name="Сatch-all">
<match url="^clients/" />
<action type="Redirect" url="customers/" />
</rule>
Поскольку в url я не использовал знак $ (конец строки), то отлавливаются все строки, начинающиеся на clients/.
А что, если у нас таких каталогов несколько (clients / partnerts / advertisers)? Пожалуйста: <match url="^(clients|partners|advertisers)/" />
А если их десяток? Причем нужно перенаправлять в разные места.
Тоже несложно - воспользуемся "картами":
<rewriteMaps>
<rewriteMap name="CatchAllRedirects">
<add key="old1" value="new1" />
<add key="old2" value="new2" />
<add key="old3" value="new3" />
<add key="old4" value="new4" />
</rewriteMap>
</rewriteMaps>
....
<rule name="Catch-all">
<match url="^([^/]+)/" />
<conditions>
<add input="{CatchAllRedirects:{R:1}}" pattern="(.+)"/>
</conditions>
<action type="Redirect" url="{C:1}/" />
</rule>
Здесь мы перенаправляем /old1/*/ в /news1/ , /old2/*/ в /news1/ и т.д.
Пока что ничего особенного. Сложности возникают, если в старой URL может быть несколько уровней вложенности. Т.е. нужно перепроверить:
/old1/*/
/old1/*/*/
/old1/*/*/*/
/old2/old3/*/
/old2/old3/*/*/*/
Казалось бы, просто меняем ([^/]+) (хоть один символ, но не слэш) на (.+) (хоть один символ, любой):
<rule name="Catch-all">
<match url="^(.+)/" />
<conditions>
<add input="{CatchAllRedirects:{R:1}}" pattern="(.+)"/>
</conditions>
<action type="Redirect" url="{C:1}/" />
</rule>
И добавляем в карту вложенные каталоги:
<rewriteMap name="CatchAllRedirects">
<add key="old1" value="new1" />
<add key="old2/old3" value="new2" />
....
</rewriteMap>
И не работает.
Потому что {R:1} (результат регулярного выражения, который используется как ключ для поиска) всегда один и только один. Правило не станет перебирать все возможные варианты (с одним слэшем, двумя, тремя) и пытаться найти соответвующий ключ в карте. Проблема в том, что при использовании карты обработка правила происходит в два шага: сначала регулярное выражение в <match>, и только потом поиск значения в карте.
Если же всё старые каталоги запихнуть в регулярное выражение и не использовать карту, то проблемы нет. Или можно сделать отдельные правила для разных уровней вложенности старого каталога. Но, конечно, если таких уровней десяток, то это непрактично...
Это просто:
<rule name="Сatch-all">
<match url="^clients/" />
<action type="Redirect" url="customers/" />
</rule>
Поскольку в url я не использовал знак $ (конец строки), то отлавливаются все строки, начинающиеся на clients/.
А что, если у нас таких каталогов несколько (clients / partnerts / advertisers)? Пожалуйста: <match url="^(clients|partners|advertisers)/" />
А если их десяток? Причем нужно перенаправлять в разные места.
Тоже несложно - воспользуемся "картами":
<rewriteMaps>
<rewriteMap name="CatchAllRedirects">
<add key="old1" value="new1" />
<add key="old2" value="new2" />
<add key="old3" value="new3" />
<add key="old4" value="new4" />
</rewriteMap>
</rewriteMaps>
....
<rule name="Catch-all">
<match url="^([^/]+)/" />
<conditions>
<add input="{CatchAllRedirects:{R:1}}" pattern="(.+)"/>
</conditions>
<action type="Redirect" url="{C:1}/" />
</rule>
Здесь мы перенаправляем /old1/*/ в /news1/ , /old2/*/ в /news1/ и т.д.
Пока что ничего особенного. Сложности возникают, если в старой URL может быть несколько уровней вложенности. Т.е. нужно перепроверить:
/old1/*/
/old1/*/*/
/old1/*/*/*/
/old2/old3/*/
/old2/old3/*/*/*/
Казалось бы, просто меняем ([^/]+) (хоть один символ, но не слэш) на (.+) (хоть один символ, любой):
<rule name="Catch-all">
<match url="^(.+)/" />
<conditions>
<add input="{CatchAllRedirects:{R:1}}" pattern="(.+)"/>
</conditions>
<action type="Redirect" url="{C:1}/" />
</rule>
И добавляем в карту вложенные каталоги:
<rewriteMap name="CatchAllRedirects">
<add key="old1" value="new1" />
<add key="old2/old3" value="new2" />
....
</rewriteMap>
И не работает.
Потому что {R:1} (результат регулярного выражения, который используется как ключ для поиска) всегда один и только один. Правило не станет перебирать все возможные варианты (с одним слэшем, двумя, тремя) и пытаться найти соответвующий ключ в карте. Проблема в том, что при использовании карты обработка правила происходит в два шага: сначала регулярное выражение в <match>, и только потом поиск значения в карте.
Если же всё старые каталоги запихнуть в регулярное выражение и не использовать карту, то проблемы нет. Или можно сделать отдельные правила для разных уровней вложенности старого каталога. Но, конечно, если таких уровней десяток, то это непрактично...
Комментариев нет:
Отправить комментарий