Перенаправление, изменение URL-адресов или перенаправление HTTP на HTTPS в Apache - все, что вы хотели знать о правилах Mod_Rewrite, но боялись спросить

264

Это канонический вопрос о mod_rewrite в Apache.

Изменение URL-адреса запроса или перенаправление пользователей на URL, отличный от того, который они первоначально запрашивали, выполняется с помощью mod_rewrite. Это включает в себя такие вещи, как:

  • Изменение HTTP на HTTPS (или наоборот)
  • Изменение запроса на страницу, которая больше не существует, на новую замену.
  • Изменение формата URL (например,? Id = 3433 в / id / 3433)
  • Представление другой страницы на основе браузера, на основе реферера, на основе всего, что возможно под луной и солнцем.
  • Все, что вы хотите возиться с URL

Все, что вы когда-либо хотели знать о правилах Mod_Rewrite, но боялись спросить!

Как я могу стать экспертом в написании правил mod_rewrite?

  • Каков основной формат и структура правил mod_rewrite?
  • Какую форму / вид регулярных выражений мне нужно иметь твердое представление?
  • Каковы наиболее распространенные ошибки / подводные камни при написании правил переписывания?
  • Что такое хороший метод для тестирования и проверки правил mod_rewrite?
  • Есть ли какие-то последствия для правил mod_rewrite для SEO или производительности, о которых мне следует знать?
  • Есть ли общие ситуации, когда mod_rewrite может показаться подходящим инструментом для работы, но это не так?
  • Каковы некоторые общие примеры?

Место для проверки ваших правил

Htaccess тестер веб - сайт является отличным местом , чтобы играть с вашими правилами и протестировать их. Он даже показывает выходные данные отладки, чтобы вы могли видеть, что соответствует, а что нет.

Кайл Брандт
источник
9
Идея, стоящая за этим вопросом, состоит в том, чтобы дать близкий путь ко всем бесконечным вопросам mod_rewrite, которые сводят наших более постоянных пользователей с ума. Это очень похоже на то, что было сделано с подсетями на serverfault.com/questions/49765/how-does-subnetting-work .
Кайл Брандт
1
Кроме того, я не хочу слишком много возражений по этому вопросу , скорее, они должны идти к ответу. Я не хочу CW это, потому что я хочу убедиться, что постер получил полную оценку за то, что я надеюсь, это ответ mod_rewrite, чтобы закончить все вопросы mod_rewrite .
Кайл Брандт
4
Извините, я проголосовал за вопрос. ;-) Я действительно думаю, что это должно появиться в (или около) вершине mod-rewriteпоисков / фильтров тегов.
Стивен Понедельник
Кто-то еще (тм) должен обрабатывать общие случаи использования. Я не знаю их достаточно хорошо, чтобы сделать это справедливо.
sysadmin1138
Возможно, этот вопрос следует добавить в вики-тег mod-rewrite, чтобы сделать путь еще короче.
beldaz

Ответы:

224

порядок синтаксиса mod_rewrite

У mod_rewrite есть некоторые определенные правила упорядочения, которые влияют на обработку. Прежде чем что-либо сделать, RewriteEngine Onнеобходимо дать директиву, поскольку это включает обработку mod_rewrite. Это должно быть перед любыми другими директивами перезаписи.

RewriteCondпредшествующее RewriteRuleделает это ЕДИНОЕ правило подчиненным условию. Любые последующие RewriteRules будут обрабатываться так, как если бы они не подлежали условным условиям.

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule $/blog/(.*)\.html        $/blog/$1.sf.html

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

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule $/blog/(.*)\.html        $/blog/$1.sf.html
RewriteRule $/blog/(.*)\.jpg         $/blog/$1.sf.jpg

Все файлы .jpg попадают на специальные страницы с ошибками сервера, а не только с ссылками, указывающими, что они пришли отсюда. Это явно не цель написания этих правил. Это можно сделать с помощью нескольких правил RewriteCond:

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.html        /blog/$1.sf.html
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.jpg         /blog/$1.sf.jpg

Но, вероятно, это должно быть сделано с более сложным синтаксисом замены.

RewriteEngine On
RewriteCond %{HTTP_REFERER}                ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.(html|jpg)        /blog/$1.sf.$2

Более сложный RewriteRule содержит условия для обработки. Последняя скобка (html|jpg)указывает RewriteRule на совпадение для любого htmlили или jpgи для представления сопоставленной строки как $ 2 в переписанной строке. Это логически идентично предыдущему блоку, с двумя парами RewriteCond / RewriteRule, он просто делает это в две строки вместо четырех.

Несколько строк RewriteCond неявно объединяются и могут быть явно ORed. Для обработки ссылок от ServerFault и Super User (явное ИЛИ):

RewriteEngine On
RewriteCond %{HTTP_REFERER}                ^https?://serverfault\.com(/|$)    [OR]
RewriteCond %{HTTP_REFERER}                ^https?://superuser\.com(/|$)
RewriteRule ^/blog/(.*)\.(html|jpg)        /blog/$1.sf.$2

Для обслуживания страниц, на которые ссылается ServerFault, браузерами Chrome (неявное И):

RewriteEngine On
RewriteCond %{HTTP_REFERER}                ^https?://serverfault\.com(/|$)
RewriteCond %{HTTP_USER_AGENT}             ^Mozilla.*Chrome.*$
RewriteRule ^/blog/(.*)\.(html|jpg)        /blog/$1.sf.$2

RewriteBaseтакже зависит от порядка, поскольку определяет, как следующие RewriteRuleдирективы обрабатывают их обработку. Это очень полезно в файлах .htaccess. Если используется, это должна быть первая директива в разделе «RewriteEngine on» в файле .htaccess. Возьмите этот пример:

RewriteEngine On
RewriteBase /blog
RewriteCond %{HTTP_REFERER}           ^https?://serverfault\.com(/|$)
RewriteRule ^(.*)\.(html|jpg)         $1.sf.$2

Это говорит mod_rewrite, что этот конкретный URL, который он обрабатывает в настоящее время, был получен посредством http://example.com/blog/ вместо физического пути к каталогу (/ home / $ Username / public_html / blog) и обрабатывается соответствующим образом. Из-за этого RewriteRuleон считает, что это начало строки после "/ blog" в URL. Здесь одно и то же написано двумя разными способами. Один с RewriteBase, другой без:

RewriteEngine On

##Example 1: No RewriteBase##
RewriteCond %{HTTP_REFERER}                                   ^https?://serverfault\.com(/|$)
RewriteRule /home/assdr/public_html/blog/(.*)\.(html|jpg)     $1.sf.$2

##Example 2: With RewriteBase##
RewriteBase /blog
RewriteCond %{HTTP_REFERER}           ^https?://serverfault\.com(/|$)
RewriteRule ^(.*)\.(html|jpg)         $1.sf.$2

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


RewriteRule, соответствующий синтаксису

Сам RewriteRule имеет сложный синтаксис для сопоставления строк. Я покрою флаги (такие как [PT]) в другом разделе. Поскольку системные администраторы учатся на примере чаще, чем читая справочную страницу, я приведу примеры и объясню, что они делают.

RewriteRule ^/blog/(.*)$    /newblog/$1

.*Конструкция соответствует любому одному символу ( .) ноль или более раз ( *). Заключив его в круглые скобки, вы должны указать строку, которая соответствует переменной $ 1.

RewriteRule ^/blog/.*/(.*)$  /newblog/$1

В этом случае первый. * НЕ был заключен в скобки, поэтому не передается переписанной строке. Это правило удаляет уровень каталога на новом блог-сайте. (/blog/2009/sample.html становится /newblog/sample.html).

RewriteRule ^/blog/(2008|2009)/(.*)$   /newblog/$2

В этом случае первое выражение в скобках устанавливает соответствующую группу. Это становится $ 1, который не нужен и, следовательно, не используется в переписанной строке.

RewriteRule ^/blog/(2008|2009)/(.*)$   /newblog/$1/$2

В этом случае мы используем $ 1 в переписанной строке.

RewriteRule ^/blog/(20[0-9][0-9])/(.*)$   /newblog/$1/$2

Это правило использует специальный синтаксис скобок, который определяет диапазон символов . [0-9] соответствует цифрам от 0 до 9. Это конкретное правило будет относиться к годам с 2000 по 2099 год.

RewriteRule ^/blog/(20[0-9]{2})/(.*)$  /newblog/$1/$2

Это делает то же самое, что и предыдущее правило, но часть {2} сообщает ему о совпадении с предыдущим символом (в данном случае это выражение в скобках) два раза.

RewriteRule ^/blog/([0-9]{4})/([a-z]*)\.html   /newblog/$1/$2.shtml

Этот регистр будет соответствовать любой строчной букве во втором совпадающем выражении и делать это для максимально возможного количества символов. \.Конструкция говорит это , чтобы рассматривать период как фактический период, а не особый характер это в предыдущих примерах. Это сломается, если имя файла содержит тире.

RewriteRule ^/blog/([0-9]{4})/([-a-z]*)\.html  /newblog/$1/$2.shtml

Это ловит имена файлов с тире в них. Однако, как -специальный символ в выражениях в скобках, он должен быть первым символом в выражении.

RewriteRule ^/blog/([0-9]{4})/([-0-9a-zA-Z]*)\.html   /newblog/$1/$2.shtml

Эта версия захватывает любое имя файла буквами, цифрами или -символом в имени файла. Вот как вы указываете несколько наборов символов в выражении в скобках.


RewriteRule flags

Флаги в правилах перезаписи имеют множество специальных значений и вариантов использования .

RewriteRule ^/blog/([0-9]{4})/([-a-z]*).\html  /newblog/$1/$2.shtml  [L]

Флаг находится [L]в конце вышеприведенного выражения. Можно использовать несколько флагов, разделенных запятой. Связанная документация описывает каждого, но вот они в любом случае:

L = последний. Прекратите обработку RewriteRules, как только этот совпадет. Заказ имеет значение!
C = цепь Продолжить обработку следующего RewriteRule. Если это правило не соответствует, то следующее правило не будет выполнено. Подробнее об этом позже.
E = установить переменную среды. Apache имеет различные переменные среды, которые могут влиять на поведение веб-сервера.
F = запрещено. Возвращает ошибку 403-Forbidden, если это правило соответствует.
G = Ушел. Возвращает ошибку 410-Gone, если это правило соответствует.
H = Обработчик. Принудительно обрабатывает запрос, как если бы он был указанным MIME-типом.
N = Далее. Заставляет правило начать все заново и заново сопоставить. БЫТЬ ОСТОРОЖЕН! Петли могут привести.
NC = Нет дела. Позволяетjpgсоответствовать как JPG, так и JPG.
NE = нет выхода. Предотвращает перезапись специальных символов (.? # & Etc) в их эквиваленты в шестнадцатеричном коде.
NS = Нет подзапросов. Если вы используете серверные включения, это предотвратит совпадение с включенными файлами.
P = прокси. Принудительно обрабатывает правило с помощью mod_proxy. Прозрачно предоставлять контент с других серверов, потому что ваш веб-сервер получает его и повторно обслуживает. Это опасный флаг, так как плохо написанный превратит ваш веб-сервер в открытый прокси, и это плохо.
PT = Pass Through. Примите во внимание операторы Alias ​​в соответствии RewriteRule.
QSA = QSAppend. Если исходная строка содержит запрос ( http://example.com/thing?asp=foo) добавить исходную строку запроса к переписанной строке. Обычно это будет отброшено. Важно для динамического контента.
R = Перенаправление. Предоставьте HTTP-перенаправление на указанный URL-адрес. Может также предоставить точный код перенаправления [R = 303]. Очень похоже на то RedirectMatch, что быстрее и должно использоваться, когда это возможно.
S = Пропустить. Пропустите это правило.
T = Тип. Укажите mime-тип возвращаемого содержимого. Очень похоже на AddTypeдирективу.

Вы знаете, как я сказал, что это RewriteCondотносится к одному и только одному правилу? Ну, вы можете обойти это, цепочки.

RewriteEngine On
RewriteCond %{HTTP_REFERER}          ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.html        /blog/$1.sf.html     [C]
RewriteRule ^/blog/(.*)\.jpg         /blog/$1.sf.jpg

Поскольку первый RewriteRule имеет флаг Chain, второе правило перезаписи будет выполнено, когда первое выполнит, то есть, когда будет найдено предыдущее правило RewriteCond. Удобно, если регулярные выражения Apache причиняют боль вашему мозгу. Однако метод «все в одной строке», на который я указываю в первом разделе, быстрее с точки зрения оптимизации.

RewriteRule ^/blog/([0-9]{4})/([-0-9a-zA-Z]*)\.html   /newblog/$1/$2.shtml

Это можно упростить с помощью флагов:

RewriteRule ^/blog/([0-9]{4})/([-0-9a-z]*)\.html   /newblog/$1/$2.shtml   [NC]

Кроме того, некоторые флаги также применяются к RewriteCond. В частности, NoCase.

RewriteCond %{HTTP_REFERER}        ^https?://serverfault\.com(/|$)     [NC]

Будет соответствовать "ServerFault.com"

sysadmin1138
источник
9
Отлично сработано. [наполнитель]
EEAA
3
Очень хороший mod_rewriteи регулярный учебник для начинающих. +1.
Стивен Понедельник,
3
Это иногда полезно знать , что RewriteCondна самом деле обрабатывается послеRewriteRule подобран. Возможно, вы захотите сказать «подробнее об этом позже» в верхней части, где вы говорите: «RewriteCond, предшествующий RewriteRule, делает это ЕДИНОЕ правило подчиненным условию». Вы можете упомянуть, что регулярные выражения являются Perl-совместимыми регулярными выражениями. Также у вас есть посторонний апостроф в «... RewriteRule считает, что это начало строки ...»
Деннис Уильямсон
2
RewriteRule ^/blog/.*/(.*)$ /newblog/$1не соответствует первому компоненту каталога - по умолчанию rewriterules являются жадными. /.*/(.*) соответствует обоим / 1 / (2) / и / 1/2/3/4/5 / (6) /, поэтому вам необходимо / [^ /] * / соответствовать только ПЕРВОМУ пути составная часть.
Adaptr
1
@ sysadmin1138, я думаю, что этот ответ хорош, но может быть лучше, если вы подробнее рассмотрите флаги E, N, NS, P, PT и S с примерами, потому что эти флаги не очевидны, как они работают и т. д.
Pacerier
39

Каков основной формат и структура правил mod_rewrite?

Я отложу до превосходного ответа sysadmin1138 по этим вопросам.

Какую форму / вид регулярных выражений мне нужно иметь твердое представление?

В дополнение к порядку синтаксиса, сопоставлению синтаксиса / регулярным выражениям и флагам RewriteRule, описанным sysadmin1138, я считаю, что стоит упомянуть, что mod_rewrite предоставляет переменные среды Apache на основе заголовков HTTP-запросов и конфигурации Apache.

Я бы порекомендовал AskApache mod_rewrite Учебник по отладке для полного списка переменных, которые могут быть доступны для mod_rewrite.

Каковы наиболее распространенные ошибки / подводные камни при написании правил переписывания?

Большинство проблем с RewriteRule проистекают из-за неправильного понимания синтаксиса PCRE / неспособности должным образом экранировать специальные символы или отсутствия понимания содержимого переменных, используемых для сопоставления.

Типичные проблемы и рекомендуемые способы устранения неполадок:

  • 500 - Внутренняя ошибка сервера - Удалите элементы управления кареткой Windows в конфигурационном файле (ах), если они есть, убедитесь, что mod_rewrite включен (оберните директивы IfModuleусловно, чтобы избежать этого сценария), проверьте синтаксис директив, закомментируйте директивы, пока проблема не будет выявлена
  • Цикл перенаправления - используйте RewriteLog и RewriteLogLevel, закомментируйте директивы, пока проблема не будет выявлена

Что такое хороший метод для тестирования и проверки правил mod_rewrite?

Во-первых, посмотрите на содержимое переменных среды, с которыми вы планируете сравнивать - если у вас установлен PHP, это так же просто, как добавить следующий блок в ваше приложение:

<?php
  var_dump($_SERVER);
?>

... затем напишите свои правила (желательно для тестирования на сервере разработки) и запишите все несоответствия или действия в файле Apache ErrorLog .

Для более сложных правил используйте RewriteLogдирективу mod_rewrite, чтобы записать активность в файл и установитьRewriteLogLevel 3

Есть ли какие-то последствия для правил mod_rewrite для SEO или производительности, о которых мне следует знать?

AllowOverride allвлияет на производительность сервера, так как Apache должен проверять .htaccessфайлы и разбирать директивы с каждым запросом - если возможно, сохраняйте все директивы в конфигурации VirtualHost для своего сайта или разрешайте .htaccessпереопределения только для каталогов, которые в них нуждаются.

В Руководстве Google для веб-мастеров прямо говорится: «Не обманывайте своих пользователей и не представляйте поисковикам другой контент, отличный от показанного пользователям, что обычно называют« маскировкой ».» - избегайте создания директив mod_rewrite, которые фильтруют роботов поисковых систем.

Роботы поисковых систем предпочитают отображение контента 1: 1: сопоставление URI (это основа для ранжирования ссылок на контент) - если вы используете mod_rewrite для создания временных перенаправлений или вы обслуживаете один и тот же контент под несколькими URI, рассмотрите возможность указания канонического URI в ваши HTML документы.

Есть ли общие ситуации, когда mod_rewrite может показаться подходящим инструментом для работы, но это не так?

Это огромная (и потенциально спорная) тема сама по себе - лучше (ИМХО) решать вопросы использования в каждом конкретном случае и позволять спрашивающим определять, соответствуют ли предложенные резолюции их потребностям.

Каковы некоторые общие примеры?

Полезные советы и советы ModArewache от AskApache охватывают практически все распространенные варианты использования, которые регулярно появляются, однако «правильное» решение для данного пользователя может зависеть от сложности конфигурации пользователя и существующих директив (именно поэтому обычно это хорошая идея, чтобы увидеть, какие другие директивы имеет пользователь при возникновении вопроса mod_rewrite).

danlefree
источник
Спасибо за ссылку AskApache. Это то, что я искал!
sica07
Клоун AskApache официально не поддерживается ASF. Многое из того, что он говорит , что это спорно или просто неправильно.
Adaptr
@adaptr Пожалуйста, поделитесь превосходными ресурсами, о которых вы, очевидно, знаете.
Данлефри
"распространенные ситуации, когда mod_rewrite может показаться подходящим инструментом для работы, но не так ли?" - простые перенаправления, где mod_rewrite еще не используется. Используйте mod_alias Redirectили RedirectMatchвместо этого. См. Также документы Apache: когда не следует использовать mod_rewrite
MrWhite,
21

Как и многие администраторы / разработчики, я годами боролся со сложностями правил переписывания и недоволен существующей документацией Apache, поэтому я решил, как личный проект, разобраться в том, как на mod_rewriteсамом деле работает и взаимодействует с остальной частью Apache. ядро, так что в последние несколько месяцев я тестировал кейсы с strace+ детализацией в исходном коде, чтобы справиться со всем этим.

Вот некоторые ключевые комментарии, которые необходимо учитывать разработчикам правил переписывания:

  • Некоторые аспекты переписывания являются общими для конфигурации сервера, виртуального хоста, каталог, .htaccess обработки однако
  • Некоторая обработка сильно отличается для корневой конфигурации (конфигурации сервера, виртуального хоста и каталога) в отличие от обработки PerDir ( .htaccess).
  • Хуже того, поскольку обработка PerDir может почти беспорядочно запускать циклы ВНУТРЕННЕГО НАПРАВЛЕНИЯ, корневые элементы конфигурации должны быть записаны с учетом того, что такая обработка PerDir может инициировать это.

Я хотел бы сказать, что из-за этого вам почти нужно разделить сообщества переписанных пользователей на две категории и рассматривать их как совершенно отдельные:

  • Те, у кого есть root-доступ к конфигурации Apache . Обычно это администратор / разработчик с выделенным сервером / виртуальной машиной приложения, и сообщение здесь довольно простое: избегайте использования .htaccessфайлов, если это возможно; сделать все на вашем сервере или vhost config. Отладка достаточно проста, так как разработчик может установить отладку и имеет доступ к файлам rewrite.log.

  • Пользователи общего хостинга (SHS) .

    • Такие пользователи должны использовать .htaccessобработку / Perdir, поскольку альтернативы нет.
    • Хуже того, уровень квалификации таких пользователей (если использовать лестничную логику, управляемую регулярным выражением mod_rewrite), как правило, значительно ниже, чем у опытных администраторов.
    • Apache и хостинг-провайдеры не предлагают никакой поддержки отладки / диагностики. Единственная диагностическая информация - это успешное перенаправление, перенаправление на неверный URI. или код состояния 404/500. Это оставляет их в замешательстве и беспомощности.
    • Apache очень слабо объясняет, как переписывание работает для этого варианта использования. Например, он не дает четкого объяснения того, какой .htaccessфайл PerDir выбран и почему. Это не объясняет тонкости езды на велосипеде PerDir и как избежать этого.

Возможно, существует третье сообщество: администратор и вспомогательный персонал поставщиков услуг SHS, которые в обоих лагерях оказываются в одной ноге и вынуждены страдать от последствий вышеуказанного.

Я написал пару постов в стиле статей (например, Подробнее об использовании правил перезаписи в файлах .htaccess ), которые охватывают множество подробных моментов, которые я не буду повторять здесь, чтобы этот пост был коротким. У меня есть собственный сервис, а также поддержка некоторых выделенных проектов и проектов VM FLOSS. Я начал использовать стандартную виртуальную машину LAMP в качестве тестовой машины для своей учетной записи SHS, но в итоге я обнаружил, что лучше создать правильную зеркальную виртуальную машину (описано здесь ).

Однако, с точки зрения того, как сообщество администраторов должно поддерживать .htaccessпользователей, я чувствую, что нам нужно развиваться и предлагать:

  • Последовательное описание того, как система перезаписи фактически работает в обработке PerDir
  • Набор руководящих принципов / лучшие практики о том, как писать .htaccessправила перезаписи
  • Простой веб-синтаксический анализатор сценариев перезаписи, похожий на анализаторы HTML-кода W3C, но с помощью которого пользователи могут вводить тестовые URI или тестовые векторы того же самого и получать немедленный журнал потока логики перезаписи /
  • Советы о том, как получить встроенную диагностику из ваших правил (например,

    • Используйте [E=VAR:EXPR]использование факта, EXPRкоторый расширит обратные ссылки ($ N или% N), чтобы сделать их доступными в качестве диагностики для целевого сценария.
    • Если вы тематически упорядочите свои правила перезаписи, используя флаги [OR], [C], [SKIP] и [L], чтобы вся схема перезаписи работала без использования внутреннего перенаправления, то вы можете добавить следующее как правило 1, чтобы избежать все циклы хлопот:

      RewriteCond %{ENV:REDIRECT_STATUS} !=""
      RewriteRule .  -  [L]
      
TerryE
источник
Это хорошо задокументировано. Почему вы говорите, что документация не объясняет это?
Адаптер
2
Все, что вам нужно сделать, это подписаться на .htaccessтемы, и вы увидите. Большинство новичков безнадежно запутались - большинство из них имеют свой первый опыт работы со службой LAMP и mod_rewrite в общей службе и поэтому не имеют корневого доступа к системным / vhost-конфигурациям, и им приходится использовать обработку dir через .htaccessфайлы. Существуют важные отличия, которые новичок должен «пролить». Я бы считал себя опытным пользователем и все еще открываю для себя тонкости. Как я уже сказал, мне пришлось использовать сканирование с помощью strace и исходного кода для проработки некоторых аспектов. В этом нет необходимости. :-(
TerryE
Я абсолютно согласен. «Нам нужно разделить сообщества переписанных пользователей на две категории и рассматривать их как совершенно отдельные». Некоторые пользователи используют виртуальный хостинг и нужно полагаться на .htaccess, что очень хрупкий, сложном и запутанном, даже для специалистов. У меня все еще проблемы.
Райан
15

Использование rewritemap

Есть много вещей, которые вы можете сделать с переписанными картами. Rewritemaps объявляются с использованием директивы Rewritemap и могут затем использоваться как в оценках RewritCond, так и в подразделах RewriteRule.

Общий синтаксис для RewriteMap:

RewriteMap MapName MapType:MapSource

Например:

RewriteMap examplemap txt:/path/to/file/map.txt

Затем вы можете использовать mapname для таких конструкций:

${examplemap:key}

Карта содержит пары ключ / значение. Если ключ найден, значение заменяется. Простые карты - это просто текстовые файлы, но вы можете использовать хэш-карты и даже запросы SQL. Более подробная информация в документах:

http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewritemap

Unescaping строки.

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

Например: я хочу проверить строку "café" в строке запроса. Тем не менее, браузер избежит этого перед отправкой на мой сервер, поэтому мне нужно будет либо выяснить, что такое экранированная версия URL для каждой строки, которую я хочу сопоставить, либо я могу просто удалить ее ...

RewriteMap unescape int:unescape

RewriteCond %{QUERY_STRING}  (location|place)=(.*)
RewriteCond ${unescape:%2}   café
RewriteRule ^/find/$         /find/1234? [L,R]

Обратите внимание, как я использую один RewriteCond для захвата аргумента в параметре строки запроса, а затем использую карту во втором rewriteCond для его удаления. Это тогда сравнивается. Также обратите внимание, что мне нужно использовать% 2 в качестве ключа в карте перезаписи, так как% 1 будет содержать «location» или «place». Когда вы используете скобки для группировки шаблонов, они также будут захвачены, независимо от того, планируете ли вы использовать результат захвата или нет ...

Крист ван Безен
источник
Последнее предложение не совсем верно. Механизм mod_rewriteрегулярных выражений поддерживает группы без захвата, например, (?:location|place)и в этом примере будет только один захват.
TerryE
12

Каковы наиболее распространенные ошибки / подводные камни при написании правил переписывания?

Очень простой подводный камень - это когда вы переписываете URL, которые изменяют видимый путь, например, с /base/1234/index.htmlна /base/script.php?id=1234. Любые изображения или CSS с относительными путями к местоположению скрипта не будут найдены клиентом. Несколько вариантов решения этой проблемы можно найти в этом FAQ .

beldaz
источник
1
Спасибо за ссылку. Особенно при работе с другими членами команды, которые не знакомы с переписыванием, я считаю, что добавление <base>тега является наиболее простым для отслеживания и в то же время включает относительные пути.
Контур