Rewriterule online

Apache mod_rewrite – Useful Tips for Testing

Lately, I’ve been dealing a lot with Apache web server’s mod_rewrite module to redirect users to alternate URLs. The mod_rewrite tool utilizes Regular Expressions (RegEx) and anyone who’s worked with them knows that they can be very cumbersome to create and test for validity. That being said, I’ve recently found several useful tools to help ease my suffering while working through to create regexs for mod_rewrite.

In some circumstances, you can also modify the behavior of a request in your settings.php file. You will see this in other documents; here we are focusing on .htaccess.

The basic formulation of any .htaccess rewrite rule includes setting a combination of rewrite condition (RewriteCond) tests along with a corresponding rule (RewriteRule) if the prior conditions pass. In most cases, these rules should be placed at any point after the RewriteEngine on line in the .htaccess file located in the website's docroot.

Creating a useable rule generally breaks down into three steps:

  1. Determining where the tests go
  2. Building the Conditions
  3. Executing the Rule

You may also find the following items handy:

Determining where the tests go

In order to do so, you will need to use "regular expressions". These are patterns, defined in a specific format that the server can understand and handle appropriately. A typical pattern to identify a number would look like this:

The square brackets contain a range of characters, and "0-9" indicates all the digits. The plus symbol indicates that the pattern will idenfiy one or more of whatever precedes the plus - so this pattern effectively means "one or more digits" - exactly what we're looking to find in our URL.

The entire "pattern" part of the rule is treated as a regular expression by default - you don't need to turn this on or activate it at all.

The first thing I hope you'll notice is that we've wrapped our pattern in brackets. This allows us to "back-reference" (refer back to) that section of the URL in the following "substitution" section. The "$1" in the substitution tells Apache to put whatever matched the earlier bracketed pattern into the URL at this point. You can have lots of backreferences, and they are numbered in the order they appear.

And so, this RewriteRule will now mean that Apache redirects all requests for{number}/ to show_a_product.php?product_id={same number}.

Regular Expressions

A complete guide to regular expressions is rather beyond the scope of this article. However, important points to remember are that the entire pattern is treated as a regular expression, so always be careful of characters that are "special" characters in regular expressions.

The most instance of this is when people use a period in their pattern. In a pattern, this actually means "any character" rather than a literal period, and so if you want to match a period (and only a period) you will need to "escape" the character - precede it with another special character, a backslash, that tells Apache to take the next character to be literal.

For example, this RewriteRule will not just match the URL "rss.xml" as intended - it will also match "rss1xml", "rss-xml" and so on.

This does not usually present a serious problem, but escaping characters properly is a very good habit to get into early. Here's how it should look:

# Получилось совсем не то, что имели в виду.

Итак, запрос прошел через все RewriteRule, после чего к нему, в случае необходимости, добавился RewriteBase. Должен ли теперь Apache отдать файл, на который показывает результирующий путь?

Как работает mod_rewrite. Флаг [L]

При составлении более-менее сложных конфигураций mod_rewrite важно понимать, что

. После того, как сработало последнее правило RewriteRule и был добавлен RewriteBase, mod_rewrite смотрит, изменился запрос или нет. Если запрос изменился, его обработка начинается заново с начала .htaccess.

Apache поступает так, потому что в процессе изменения запроса он мог быть перенаправлен в другую директорию. В ней может быть собственный .htaccess, который не участвовал в предыдущей обработке запроса. В этом же новом .htaccess могут быть правила, которые влияют на обработку запроса — как правила mod_rewrite, так и правила других модулей. Чтобы корректно обработать эту ситуацию, Apache должен запустить весь цикл обработки заново.

— Постойте, но ведь есть флаг [L], который останавливает обработку запроса mod_rewrite'ом!

Не совсем так. Флаг [L] останавливает текущую итерацию обработки запроса. Однако если запрос был изменен теми RewriteRule, которые все-таки успели отработать, Apache запустит цикл обработки запроса заново с первого RewriteRule.

RewriteBase /

RewriteRule ^a.html$ b.html [L]
RewriteRule ^b.html$ a.html [L]

Пример выше приведет к бесконечному циклу перенаправлений и к «Internal Server Error» в итоге. В этом примере бесконечный цикл очевиден, однако в более сложных конфигурациях может потребоваться покопаться в правилах, чтобы определить, какие запросы зацикливаются между собой.

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

  1. Когда используется внешний редирект — [L,R=301] или [L,R=302]. В случае внешнего редиректа дальнейшая обработка запроса нежелательна (см. ниже про флаг [R]), и ее лучше остановить.
  2. Когда в .htaccess есть зацикливание, от которого не избавиться, и обработку запроса mod_rewrite'ом нужно принудительно прекратить. В этом случае используется специальная конструкция — см. в конце статьи советы на эту тему.

А вот приведенный ниже пример зацикливаться не будет. Попробуйте определить, почему, и какой в итоге файл будет отдан Apache'м.

For example, you might define a
RewriteMap as:

You would then be able to use this map in a
RewriteRule as follows:

The meaning of the MapTypeOptions argument depends on
particular MapType. See the
Using RewriteMap for
more information.

The following combinations for MapType and
MapSource can be used:

Further details, and numerous examples, may be found in the RewriteMap HowTo

The RewriteOptions directive sets some
special options for the current per-server or per-directory
configuration. The Option string can currently
only be one of the following:

This forces the current configuration to inherit the
configuration of the parent. In per-virtual-server context,
this means that the maps, conditions and rules of the main
server are inherited. In per-directory context this means
that conditions and rules of the parent directory's
.htaccess configuration or
sections are inherited. The inherited rules are virtually copied
to the section where this directive is being used. If used in
combination with local rules, the inherited rules are copied behind
the local rules. The position of this directive - below or above
of local rules - has no influence on this behavior. If local
rules forced the rewriting to stop, the inherited rules won't
be processed.

Rules inherited from the parent scope are applied
after rules specified in the child scope.

Like Inherit above, but the rules from the parent scope
are applied before rules specified in the child scope.
Available in Apache HTTP Server 2.3.10 and later.

What doesn't work?

  • RewriteMaps aren't supported because of the amount of work needed to implement it here and the ease with which one can test them already.
  • RewriteBase isn't supported because it doesn't really make sense here.
  • The other mod_rewrite options aren't interesting in this context either.

5) Перенаправление домена на новый поддомен или папку.

Допустим, Вы сделали редизайн на сайте и обновленный сайт находится в папке “new” в корне сайта. То есть новый сайт доступен по адресу “”. Перенос файлов из одного места в другое может быть довольно трудоемким процесом, так что просто добавьте следующие строки в файл .htaccess и разместите его в корневой папке:

htaccess rewrite rules generator

or show hotlinked notice error