Статьи

Изучите Apache mod_rewrite: 13 реальных примеров

mod_rewrite Флаги

mod_rewrite использует «флаги», чтобы предоставить нашим условиям перезаписи и правилам дополнительные функции. Мы добавляем флаги в конце условия или правила, используя квадратные скобки, и разделяем несколько флагов запятой. Основные флаги, с которыми вам необходимо ознакомиться:

  • last|L — флаг Last указывает Apache прекратить серию условий перезаписи и правила перезаписи таким же образом, как } завершит блок операторов в PHP. Обратите внимание, что этот флаг не прекращает обработку mod_rewrite!
  • nocase|NC — Флаг No Case указывает Apache игнорировать регистр строки в регулярном выражении и часто необходим при написании оператора RewriteCond который соответствует переменной {HTTP_HOST} для доменного имени, которое не {HTTP_HOST} регистр.
  • redirect|R — Флаг Redirect используется для запуска внешнего (видимого) перенаправления. По умолчанию это означает, что Apache выдаст ответ HTTP 302, чтобы указать, что документ был временно перемещен, но вы можете указать код HTTP, если хотите. Например, вы можете использовать [R=301] чтобы заставить Apache выдавать ответ HTTP 301 (постоянно перемещенный), что часто бывает полезно, если вам нужны поисковые системы для переиндексации измененного URI.
  • qsappend|QSA — Флаг Query String Appended используется для «прохождения» через существующие строки запроса. Вы также можете определить новую строку запроса, к которой будет добавлена ​​старая строка, но будьте осторожны, чтобы не дублировать имена ключей. Отказ от использования флага QSA приведет к созданию строки запроса во время перенаправления, чтобы уничтожить существующую строку запроса.
  • forbidden|F — флаг «Запрещено» используется для указания Apache, когда не следует предоставлять страницу в ответ на запрос. В результате Apache выдаст ответ HTTP 403, который можно использовать для защиты файлов от просмотра неавторизованными посетителями, пиявок пропускной способности и так далее.
  • ornext|OR — Флаг OR позволяет вам комбинировать условия перезаписи с логическим отношением OR в противоположность стандартному AND.
  • next|N — флаг Next указывает mod_rewrite перезапустить процесс перезаписи из первого правила, но использовать URI, возвращенный из последнего обработанного правила перезаписи. Это полезно для замены символов в {REQUEST_URI} когда вы не знаете, сколько их будет.

Вы можете прочитать о других доступных флагах на странице документации Apache.org mod_rewrite .

Комментарии к mod_rewrite

Оператор RewriteEngine on необходим в начале любого кода mod_rewrite, но он также полезен в другой роли. Как хороший программист, вы знаете, как важны комментарии в вашем коде. mod_rewrite позволяет закомментировать весь блок кода mod_rewrite, обернув код в RewriteEngine off и RewriteEngine on операторах:

 RewriteEngine off  RewriteCond %{HTTP_HOST} !^www.example.com$ [NC]  RewriteRule .? http://www.example.com%{REQUEST_URI} [R=301,L]  RewriteEngine on 

Ни одно из приведенных выше утверждений не будет прочитано модулем mod_rewrite. Операторы RewriteEngine могут быть очень полезны при разработке нового кода mod_rewrite — просто используйте их как оболочку /* ... */ для комментариев PHP.

mod_rewrite Советы

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

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

Люди часто пытаются использовать базу данных для перенаправления из заголовка или другого подобного поля к определенному значению идентификатора. Для этой цели у mod_rewrite есть оператор RewriteMap , но у вас должен быть доступ к основному файлу конфигурации Apache: httpd.conf . Как правило, вы будете иметь доступ к этому файлу только в том случае, если вы владеете и управляете сервером. Вместо этого полностью избегайте проблемы и используйте поле ID для создания своих ссылок.

Помните, что пробелы обозначаются как %20 в URI, поэтому вам необходимо заменить их в своем коде PHP. Функция PHP str_replace идеально подходит для этой задачи. Как правило, нам нужно заменить пробелы на %20 при генерации ссылок и преобразовать %20 обратно в пробелы при чтении значений строки запроса из массива $_GET . Однако при работе с уникальными значениями полей базы данных, которые содержат пробелы, я предпочитаю использовать символ подчеркивания для замены пробелов в результирующих ссылках. Для этого вы можете использовать следующий код PHP:

 $name = str_replace ( ' ', '_', $name ); 

Будьте осторожны, чтобы не сломать существующие относительные ссылки при реализации новой схемы URI. Разработчики часто удивляются, когда внезапно перестают работать их CSS, файлы JavaScript и изображения. Помните, что относительные ссылки относятся к текущему URI на стороне браузера — это запрошенный URI, а не переписанный. В зависимости от конфигурации вашего сайта вам может потребоваться использовать абсолютные URI или <base> HTML <base> для всех ваших статических ресурсов.

13 примеров mod_rewrite

Ранее мы рассмотрели пример, который принудительно включал часть www доменного имени для каждого запроса. Давайте посмотрим еще на несколько примеров и посмотрим, насколько полезным может быть mod_rewrite.

1. Принудительное использование www для домена при сохранении поддоменов.

 RewriteCond %{HTTP_HOST} ^([az.]+)?example.com$ [NC]  RewriteCond %{HTTP_HOST} !^www. [NC]  RewriteRule .? http://www.%1example.com%{REQUEST_URI} [R=301,L] 

Это правило захватывает необязательный поддомен, используя переменную %1 , и, если оно не начинается с www., Перенаправляет с www. добавлен в поддомен. Домен и оригинал {REQUEST_URI} добавляются к результату.

2. Исключение www из домена

 RewriteCond %{HTTP_HOST} !^example.com$ [NC]  RewriteRule .? http://example.com%{REQUEST_URI} [R=301,L] 

3. Избавляемся от www, но сохраняем поддомен

 RewriteCond %{HTTP_HOST} ^www.(([a-z0-9_]+.)?example.com)$ [NC]  RewriteRule .? http://%1%{REQUEST_URI} [R=301,L] 

Здесь субдомен захватывается в %2 (внутренний атом), но, поскольку он необязательный и уже захвачен в переменной %1 , все, что вам нужно, это %1 для субдомена.

4. Предотвращение хотлинкинга изображения

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

 RewriteCond %{HTTP_REFERER} !^$  RewriteCond %{HTTP_REFERER} !^http://(www.)?example.com/ [NC]  RewriteRule .(gif|jpg|png)$ - [F] 

Если значение {HTTP_REFERER} не пустое или из вашего собственного домена (example.com), это правило будет блокировать просмотр URI, заканчивающихся на .gif , .jpg или .png с использованием флага запрета F

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

 RewriteCond %{HTTP_REFERER} !^$  RewriteCond %{HTTP_REFERER} !^http://(www.)?example.com/.*$ [NC]  RewriteRule .(gif|jpg|png)$ http://www.example.com/hotlinked.gif [R=301,L] 

Вместо того, чтобы блокировать URI, вышеприведенное правило переписывает его для определенного изображения в нашем домене. То, что появляется на этом изображении, полностью зависит от вашего воображения!

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

 RewriteCond %{HTTP_REFERER} !^http://(www.)?leech_site.com/ [NC]  RewriteRule .(gif|jpg|png)$ - [F,L] 

Это правило блокирует все запросы, для которых в поле {HTTP_REFERER} указано {HTTP_REFERER} имя домена.

Конечно, приведенные выше правила основаны на правильности установки значения {HTTP_REFERER} . Обычно это так, но если вы предпочитаете использовать IP-адрес, используйте вместо него {REMOTE_ADDR} .

5. Перенаправление на страницу 404, если каталог и файл не существуют

Если ваш хост не обеспечивает перенаправление «файл не найден», создайте его самостоятельно!

 RewriteCond %{REQUEST_FILENAME} !-f  RewriteCond %{REQUEST_FILENAME} !-d  RewriteRule .? /404.php [L] 

Здесь -f соответствует существующему имени файла, а -d соответствует существующему имени каталога. Этот сценарий проверяет, что запрашиваемое имя файла не является существующим именем файла или каталога, прежде чем оно перенаправляется в сценарий 404.php . Вы можете расширить этот скрипт: включить URI в строку запроса, добавив ?url=$1 сразу после URI:

 RewriteRule ^/?(.*)$ /404.php?url=$1 [L] 

Таким образом, ваш скрипт 404.php может что-то делать с запрошенным URL-адресом: отображать его в сообщении, отправлять в уведомлении по электронной почте, выполнять поиск и так далее.

6. Переименование ваших каталогов

Если вы переместили файлы на своем сайте, изменив имена каталогов, попробуйте это:

 RewriteRule ^/?old_directory/([az/.]+)$ new_directory/$1 [R=301,L] 

Я включил символ буквальной точки (не метасимвол «любой символ») в набор, чтобы разрешить расширения файлов.

7. Преобразование старых .html ссылок в новые .php ссылки.

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

 RewriteRule ^/?([az/]+).html$ $1.php [L] 

Это не перенаправление, поэтому оно будет невидимым для ваших посетителей. Чтобы сделать его постоянным (и видимым), измените флаг на [R=301,L] .

8. Создание ссылок без расширений

Если на вашем сайте используются файлы PHP, и вы хотите, чтобы ваши ссылки было легче запомнить, или вы просто хотите скрыть расширение файла, попробуйте следующее:

 RewriteRule ^/?([az]+)$ $1.php [L] 

Если у вас есть смесь файлов .html и .php , вы можете использовать операторы RewriteCond чтобы проверить, существует ли имя файла с любым расширением в виде файла:

 RewriteCond %{REQUEST_FILENAME}.php -f  RewriteRule ^/?([a-zA-Z0-9]+)$ $1.php [L]  RewriteCond %{REQUEST_FILENAME}.html -f  RewriteRule ^/?([a-zA-Z0-9]+)$ $1.html [L] 

Если имя файла существует с расширением .php , будет выбрано это правило.

9. Проверка ключа в строке запроса

Если вам нужно указать конкретное значение ключа в строке запроса, вы можете проверить его наличие с помощью инструкции RewriteCond :

 RewriteCond %{QUERY_STRING} !uniquekey=  RewriteRule ^/?script_that_requires_uniquekey.php$ other_script.php [QSA,L] 

Приведенный выше код проверит переменную {QUERY_STRING} на отсутствие ключа uniquekey и, если {REQUEST_URI} — это script_that_requires_uniquekey , он перенаправит на альтернативный URI.

10. Удаление строки запроса

Mod_rewrite в Apache автоматически проходит через строку запроса, если вы не выполните одно из следующих действий:

  • Назначьте новую строку запроса (вы можете сохранить исходную строку запроса, добавив флаг QSA, например, [QSA,L] ).
  • Добавить ? после имени файла (например, index.php? ). ? не будет отображаться в поле местоположения браузера.

11. Перенаправление рабочего URI в новый формат

Вот кудрявый. Скажем, например, что у нас есть набор рабочих URL, которые выглядят так: /index.php?id=nnnn . Однако нам бы очень хотелось изменить их на /nnnn и убедиться, что поисковые системы обновляют свои индексы до нового формата URI. Во-первых, нам нужно было бы перенаправить старые URI на новые, чтобы поисковые системы обновляли свои индексы, но нам все равно пришлось бы переписать новый URI обратно на старый, чтобы скрипт index.php работал. У меня твоя голова кружится?

Хитрость заключается в том, чтобы поместить в строку запроса код маркера, который не будет виден посетителям. Мы перенаправляем со старой ссылки на новый формат, только если «маркер» отсутствует в строке запроса. Затем мы переписываем ссылку нового формата обратно в старый формат и добавляем маркер в строку запроса, используя флаг QSA, чтобы убедиться, что мы не удаляем существующую строку запроса. Вот как это делается:

 RewriteCond %{QUERY_STRING} !marker  RewriteCond %{QUERY_STRING} id=([-a-zA-Z0-9_+]+)  RewriteRule ^/?index.php$ %1? [R=301,L]   RewriteRule ^/?([-a-zA-Z0-9_+]+)$ index.php?marker&id=$1 [L] 

Здесь оригинальный URI, http://www.example.com/index.php?id=nnnn , не содержит маркер, поэтому он перенаправляется по первому правилу на http://www.example.com/nnnn с ответ HTTP 301. Второе правило переписывает http://www.example.com/nnnn обратно на http://www.example.com/index.php?marker&id=nnnn , добавляя marker и id=nnnn в новую строку запроса; затем процесс mod_rewrite запускается заново.

Во второй итерации маркер сопоставляется, поэтому первое правило игнорируется и, поскольку в index.php?marker&id=nnnn есть символ точки, второе правило также игнорируется … и мы закончили!

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

12. Обеспечение использования безопасного сервера

Apache может определить, используете ли вы безопасный сервер двумя способами: с помощью переменных {HTTPS} или {SERVER_PORT} :

 RewriteCond %{REQUEST_URI} ^secure_page.php$  RewriteCond %{HTTPS} !on  RewriteRule ^/?(secure_page.php)$ https://www.example.com/$1 [R=301,L] 

В приведенном выше примере проверяется, что значение {REQUEST_URI} равно нашему безопасному сценарию страницы, а значение {HTTPS} не равно on. Если оба эти условия выполнены, запрос перенаправляется на URI защищенного сервера. В качестве альтернативы вы можете сделать то же самое, протестировав значение {server_port} , где 443 — это обычно безопасный порт сервера:

 RewriteCond %{REQUEST_URI} ^secure_page.php$  RewriteCond %{SERVER_PORT} !^443$  RewriteRule ^/?(secure_page.php)$ https://www.example.com/$1 [R=301,L] 

13. Обеспечение безопасности сервера только на выбранных страницах

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

 RewriteCond %{SERVER_PORT} !^443$  RewriteRule ^/?(page1|page2|page3|page4|page5)$  https://www.example.com/%1 [R=301,L] 

Вот как вы перенаправили бы запросы на страницы, не требующие безопасного сервера, обратно на порт 80:

 RewriteCond %{ SERVER_PORT } ^443$  RewriteRule !^/?(page6|page7|page8|page9)$ http://www.example.com%{REQUEST_URI} [R=301,L] 

Резюме

Apache mod_rewrite в основном используется для поддержки SEO и удобных для пользователя URI, но также является чрезвычайно гибким инструментом для других важных задач перенаправления. Если вы хотите узнать больше, вот несколько очень полезных ресурсов, которые я нашел:

Регулярные выражения

Если вам понравилось читать этот пост, вы полюбите Learnable ; место, чтобы узнать новые навыки и приемы у мастеров. Участники получают мгновенный доступ ко всем электронным книгам и интерактивным онлайн-курсам SitePoint, таким как PHP и MySQL для веб-разработчиков для начинающих .

Перейти на страницу: 1 | 2