порядок синтаксиса 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"