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

  

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

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

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

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

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

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

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

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

251 голос | спросил Kyle Brandt 20 MonEurope/Moscow2010-12-20T19:59:18+03:00Europe/Moscow12bEurope/MoscowMon, 20 Dec 2010 19:59:18 +0300 2010, 19:59:18

5 ответов


216

порядок синтаксиса 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, перенаправляйте запросы блога на специальные страницы сервера (мы просто такие специальные). Однако, если в вышеупомянутом блоке была дополнительная строка RewriteRule:

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

Все файлы .jpg перейдут на специальные страницы serverfault, а не только те, у которых есть ссылка, указывающая, что она появилась здесь. Это явно не цель того, как эти правила написаны. Это можно сделать с помощью нескольких правил 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 неявно ANDed и могут быть явно ORed. Чтобы обрабатывать рефереры как с ServerFault, так и с Super User (явным OR):

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

Чтобы обслуживать серверные страницы с браузерами Chrome (неявные AND):

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]) в другом разделе. Поскольку Sysadmins учатся на примере чаще, чем путем чтения a man-страница Я приведу примеры и объясню, что они делают.

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

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

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

В этом случае первый. * не был заключен в parens, поэтому не предоставляется перезаписанная строка. Это правило удаляет уровень каталогов на новом блоге. (/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

В этом правиле используется специальный синтаксис скобок, который задает символ range . [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

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

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

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


Флаги RewriteRule

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

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

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

L = Последнее. Прекратите обработку RewriteRules после этого. Счет заказов!
C = Цепочка. Продолжайте обработку следующего RewriteRule. Если это правило не соответствует, то следующее правило не будет выполнено. Подробнее об этом позже.
E = Установить переменную окружения. Apache имеет различные переменные среды, которые могут влиять на поведение веб-сервера.
F = Запрещено. Возвращает ошибку 403-Forbidden, если это правило соответствует.
G = Gone. Возвращает ошибку 410-Gone, если это правило соответствует.
H = Обработчик. Заставляет запрос обрабатываться так, как если бы он был указан MIME-типом.
N = Далее. Заставляет правило начинать заново и повторно сопоставлять. БЫТЬ ОСТОРОЖЕН! Возможны петли.
NC = Нет случая. Позволяет jpg соответствовать как jpg, так и JPG.
NE = Нет выхода. Предотвращает переписывание специальных символов (.? # И т. Д.) В их эквиваленты шестнадцатеричного кода.
NS = Без подзапросов. Если вы используете серверные компоненты, это предотвратит совпадение с включенными файлами.
P = Прокси. Заставляет правило обрабатываться mod_proxy. Прозрачно предоставлять контент с других серверов, потому что ваш веб-сервер извлекает его и повторно обслуживает. Это опасный флаг, так как плохо написанный превратит ваш веб-сервер в открытый прокси, и это плохо.
PT = Пропустить. Учитывайте утверждения Alias ​​в сопоставлении RewriteRule.
QSA = QSAppend. Когда исходная строка содержит запрос ( http://example.com/thing?asp=foo ), добавьте исходный запрос string в перезаписанную строку. Обычно это было бы отброшено. Важно для динамического содержимого.
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 20 MonEurope/Moscow2010-12-20T20:44:28+03:00Europe/Moscow12bEurope/MoscowMon, 20 Dec 2010 20:44:28 +0300 2010, 20:44:28
38
  

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

Я отчитаю превосходный ответ sysadmin1138 на эти вопросы.

  

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

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

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

  

Каковы наиболее распространенные   ошибки /ловушки при написании перезаписи   правила?

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

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

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

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

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

<?php
  var_dump($_SERVER);
?>

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

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

  

Есть ли SEO или производительность?   последствия правил mod_rewrite I   должен знать?

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

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

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

  

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

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

  

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

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

ответил danlefree 21 TueEurope/Moscow2010-12-21T04:00:35+03:00Europe/Moscow12bEurope/MoscowTue, 21 Dec 2010 04:00:35 +0300 2010, 04:00:35
20

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

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

  • Некоторые аспекты переписывания являются общими для конфигурации сервера, виртуального хоста, каталога, .htaccess обработки однако
  • Некоторая обработка сильно отличается для корневой конфигурации (конфигурации сервера, виртуального хоста и каталога) в отличие от обработки PerDir (.htaccess).
  • Хуже того, что обработка PerDir может почти без разбора вызвать циклический цикл INTERNAL REDIRECT, корневые элементы конфигурации должны быть записаны, что такая обработка PerDir может вызвать это.

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

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

  • Пользователи службы общего размещения (SHS) .

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

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

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

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

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

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

      RewriteCond %{ENV:REDIRECT_STATUS} !=""
      RewriteRule .  -  [L]
      
ответил TerryE 14 Jpm1000000pmSat, 14 Jan 2012 20:50:34 +040012 2012, 20:50:34
15

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

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

Общий синтаксис для 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_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 в качестве ключа в rewritemap, поскольку% 1 будет содержать «местоположение» или «место». Когда вы используете круглые скобки для группировки паттернов, они также будут захвачены, если вы планируете использовать результат захвата или нет ...

ответил Krist van Besien 6 PMpSat, 06 Apr 2013 15:57:53 +040057Saturday 2013, 15:57:53
12
  

Каковы наиболее распространенные   ошибки /ловушки при написании перезаписи   правила?

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

ответил beldaz 1 Jam1000000amSat, 01 Jan 2011 07:02:48 +030011 2011, 07:02:48

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132