Apache Версия 2.0 Сервера HTTP
первоначально написанный
Ралф С. Энджелшол <rse@apache.org>
декабрь 1997
этот документ добавляется
mod_rewrite
reference documentation
. это описывает, как можно использовать Апача
mod_rewrite
решить типичные проблемы НА ОСНОВЕ URL, с которыми webmasters являются commonony, которому противостоят. Мы даем детализированные описания о том, как решить каждую проблему, формируя URL, переписывая rulesets.
mod_rewrite
Apache модуль
mod_rewrite
является убийцей один, то есть это - действительно сложный модуль, который обеспечивает мощный способ сделать манипуляции URL. С этим Вы можете сделать почти все типы манипуляций URL, о которых Вы когда-либо мечтали. Цена, которую Вы должны заплатить, должна принять сложность, потому что
mod_rewrite
's главный недостаток - то, что не легко понять и использовать для новичка. И даже Apacheские эксперты иногда обнаруживают новые аспекты где
mod_rewrite
может помочь.
другими словами: С
mod_rewrite
Вы или стреляете себя в ногу в первый раз и никогда не используете это снова или любите это для остальной части вашей жизни из-за ее власти. Эта бумага пробует дать Вам несколько начальных событий успеха, чтобы избежать первого случая, представляя уже изобретенные решения Вас.
здесь прибывают много практических решений, которые я или изобрел самостоятельно или собрал из решений других людей в прошлом. Не стесняйтесь изучать черную магию переписывания URL от этих примеров.
[PT]
флаг, дополнительно используя
mod_alias
и
mod_userdir
, и т.д. Или переписывая ruleset, чтобы сойтись
.htaccess
контекст вместо в-сервер контекста. Всегда пробуйте понять то, что действительно делает специфический ruleset прежде, чем Вы используете это. Это избегает проблем.
на некотором webservers есть больше чем один URL для ресурса. Обычно есть канонические URL (который должен фактически использоваться и распределен), и те, которые являются только shortcuts, внутренние, и т.д. Независимый, из какого URL пользователь снабжал запросом, он должен наконец видеть канонический только.
мы делаем внешний HTTP переадресовывает для всех неканонических URL, чтобы установить их в представлении местоположения Браузера и для всех последующих запросов. В примере ruleset ниже мы заменяем
/~user
каноническим
/u/user
и установите отсутствие, тащащее разрез для
/u/user
.
RewriteRule ^/ ~ ([^/]+)/?(.*) / u /$1/$2 [ R ] RewriteRule ^/([uge])/( [^/]+ )$ /$1/$2 / [ R ]
# For sites running on a port other than 80 RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC] RewriteCond %{HTTP_HOST} !^$ RewriteCond %{SERVER_PORT} !^80$ RewriteRule ^/(.*) http://fully.qualified.domain.name:%{SERVER_PORT}/$1 [L,R] # And for a site running on port 80 RewriteCond %{HTTP_HOST} !^fully\.qualified\.domain\.name [NC] RewriteCond %{HTTP_HOST} !^$ RewriteRule ^/(.*) http://fully.qualified.domain.name/$1 [L,R]
DocumentRoot
обычно
DocumentRoot
из webserver непосредственно имеет отношение с URL "
/
". Но часто эти данные не действительно высокопоставленного приоритета, это - возможно только одно юридическое лицо большого количества объединений данных. Например на наших участках Интранета есть
/e/www/
(начальная страница для WWW),
/e/sww/
(начальная страница для Интранета) и т.д. Теперь, потому что данные
DocumentRoot
пребывание в
/e/www/
мы должны были удостовериться, что весь inlined отображает и другой материал в этой работе объединения данных для последующих запросов.
мы переадресовываем URL
/
к
/e/www/
:
RewriteEngine on RewriteRule ^/$ /e/www/ [ R ]
отметить, что это может также быть обработано, используя
RedirectMatch
директива:
RedirectMatch ^/$ http://example.com/e/www/
каждый webmaster может петь песню о проблеме тянущегося разреза на URL, ссылающихся на справочники. Если они отсутствуют, сервер сваливает ошибку, потому что, если Вы говорите
/~quux/foo
вместо
/~quux/foo/
тогда сервер ищет a
файл
названный
foo
. и потому что этот файл - справочник, это жалуется. Фактически это пробует установить это непосредственно в большинстве случаев, но иногда этот механизм должен быть эмулирован Вами. Например после того, как Вы сделали много сложных переписываний URL к подлинникам CGI и т.д.
решение этой тонкой проблемы состоит в том, чтобы позволить серверу добавлять тянущийся разрез автоматически. Чтобы сделать это правильно, мы должны использовать внешнее, переадресовывают, таким образом браузер правильно просит последующие изображения и т.д. Если бы мы только сделали внутреннее переписывает, это только работало бы для директивной страницы, но пошло бы не так, как надо, когда любые изображения включены в эту страницу с относительными URL, потому что браузер просил бы в - выровненный объект. Например, запрос о
image.gif
в
/~quux/foo/index.html
стал бы
/~quux/image.gif
без внешнего переадресовывают!
Так, чтобы сделать эту уловку, мы пишем:
RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo $ foo / [ R ]
сумасшедшее и ленивый может даже сделать следующее в высокопоставленном
.htaccess
файл их homedir. Но уведомление, что это создает некоторую обработку наверху.
RewriteEngine on RewriteBase /~quux/ RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^(.+ [^/] )$ $1 / [R]
мы хотим создать гомогенное и последовательное расположение URL по всем WWW-серверам на Интранете webcluster, то есть всех URL (в местный сервер определения и таким образом иждивенец сервера!) становившийся фактически сервер независимый ! То, что мы хотим, должно дать WWW namespace последовательное независимое от сервера расположение: никакому URL придется не включить никакой физически правильный целевой сервер. Сама группа должна вести нас автоматически физическому целевому хозяину.
сначала, знание целевых серверов прибывают от (распределенных) внешних карт, которые содержат информацию, где наши пользователи, группы и объекты остаются. Формы
user1 server_of_user1 user2 server_of_user2 : :
мы помещаем их в файлы
map.xxx-to-host
. секунда мы должны проинструктировать все серверы переадресовывать URL форм
/u/user/anypath /g/group/anypath /e/entity/anypath
к
http://physical-host/u/user/anypath http://physical-host/g/group/anypath http://physical-host/e/entity/anypath
когда URL не в местном масштабе действителен к серверу. Следующий ruleset делает это для нас помощью файлов карты (предполагающий, что server0 является сервером по умолчанию, который будет использоваться, если пользователь не будет иметь никакого входа в карте):
RewriteEngine on RewriteMap user-to-host txt:/path/to/map.user-to-host RewriteMap group-to-host txt:/path/to/map.group-to-host RewriteMap entity-to-host txt:/path/to/map.entity-to-host RewriteRule ^/u/ ([^/]+) /?(.*) http:// ${user-to-host:$1|server0} /u/$1/$2 RewriteRule ^/g/ ([^/]+) /?(.*) http:// ${group-to-host:$1|server0} /g/$1/$2 RewriteRule ^/e/ ([^/]+) /?(.*) http:// ${entity-to-host:$1|server0} /e/$1/$2 RewriteRule ^/([uge])/([^/]+)/?$ /$1/$2/.www/ RewriteRule ^/([uge])/([^/]+)/([^.]+.+) /$1/$2/.www/$3\
много webmasters спросили решение следующей ситуации: Они хотели переадресовать только весь homedirs на webserver к другому webserver. Они обычно нуждаются в таких вещах, устанавливая более новый webserver, который заменит старый в течение долгого времени.
решение тривиально с
mod_rewrite
. на старом webserver мы только переадресовываем все
/~user/anypath
URL к
http://newserver/~user/anypath
.
RewriteEngine on RewriteRule ^/~(.+) http:// newserver /~$1 [R,L]
некоторые участки с тысячами пользователей обычно используют структурированное homedir расположение, то есть каждый homedir находится в подсправочнике, который начинается например с первого характера имени пользователя. Так,
/~foo/anypath
/home/
f
/foo/.www/anypath
в то время как
/~bar/anypath
/home/
b
/bar/.www/anypath
.
мы используем следующий ruleset, чтобы расширить URL тильды в точно вышеупомянутое расположение.
RewriteEngine on RewriteRule ^/~( ([a-z]) [a-z0-9]+)(.*) /home/ $2 /$1/.www$3
это действительно - ужасный пример: заявление убийцы, которое тяжело использует в-справочник
RewriteRules
получить гладкий взгляд и чувство на Сети, в то время как ее структура данных никогда не затрогается или приспосабливается. Фон:
net.sw
является моим архивом свободно доступных пакетов программ Unix, которые я начал собирать в 1992. Это является и моим хобби и работой к к этому, потому что, в то время как я изучаю информатику, я также работал много лет как система и администратор сети в моем свободном времени. Каждую неделю я нуждаюсь в своего рода программном обеспечении, таким образом я создал глубокую иерархию справочников, где я хранил пакеты:
drwxrwxr-x 2 netsw users 512 Aug 3 18:39 Audio/ drwxrwxr-x 2 netsw users 512 Jul 9 14:37 Benchmark/ drwxrwxr-x 12 netsw users 512 Jul 9 00:34 Crypto/ drwxrwxr-x 5 netsw users 512 Jul 9 00:41 Database/ drwxrwxr-x 4 netsw users 512 Jul 30 19:25 Dicts/ drwxrwxr-x 10 netsw users 512 Jul 9 01:54 Graphic/ drwxrwxr-x 5 netsw users 512 Jul 9 01:58 Hackers/ drwxrwxr-x 8 netsw users 512 Jul 9 03:19 InfoSys/ drwxrwxr-x 3 netsw users 512 Jul 9 03:21 Math/ drwxrwxr-x 3 netsw users 512 Jul 9 03:24 Misc/ drwxrwxr-x 9 netsw users 512 Aug 1 16:33 Network/ drwxrwxr-x 2 netsw users 512 Jul 9 05:53 Office/ drwxrwxr-x 7 netsw users 512 Jul 9 09:24 SoftEng/ drwxrwxr-x 7 netsw users 512 Jul 9 12:17 System/ drwxrwxr-x 12 netsw users 512 Aug 3 20:15 Typesetting/ drwxrwxr-x 10 netsw users 512 Jul 9 14:08 X11/
в июле 1996 я решил сделать эту публику архива к миру через хороший интерфейс Сети. "Хороший" означает, что я хотел предложить интерфейс, где Вы можете рассмотреть непосредственно через иерархию архива. И "хороший" означает, что я не сделал требуемый, чтобы изменить что - нибудь в этой иерархии - не даже, помещая некоторые подлинники CGI наверху этого. Почему? Поскольку вышеупомянутая структура должна быть позже доступный через ПРОГРАММУ ПЕРЕДАЧИ ФАЙЛОВ также, и я не хотел, чтобы никакая Сеть или материал CGI была там.
решение имеет две части: первое - ряд подлинников CGI, которые создают все страницы на всех директивных непрерывных уровнях. Я помещал их под
/e/netsw/.www/
следующим образом:
-rw-r--r-- 1 netsw users 1318 Aug 1 18:10 .wwwacl drwxr-xr-x 18 netsw users 512 Aug 5 15:51 DATA/ -rw-rw-rw- 1 netsw users 372982 Aug 5 16:35 LOGFILE -rw-r--r-- 1 netsw users 659 Aug 4 09:27 TODO -rw-r--r-- 1 netsw users 5697 Aug 1 18:01 netsw-about.html -rwxr-xr-x 1 netsw users 579 Aug 2 10:33 netsw-access.pl -rwxr-xr-x 1 netsw users 1532 Aug 1 17:35 netsw-changes.cgi -rwxr-xr-x 1 netsw users 2866 Aug 5 14:49 netsw-home.cgi drwxr-xr-x 2 netsw users 512 Jul 8 23:47 netsw-img/ -rwxr-xr-x 1 netsw users 24050 Aug 5 15:49 netsw-lsdir.cgi -rwxr-xr-x 1 netsw users 1589 Aug 3 18:43 netsw-search.cgi -rwxr-xr-x 1 netsw users 1885 Aug 1 17:41 netsw-tree.cgi -rw-r--r-- 1 netsw users 234 Jul 30 16:35 netsw-unlimit.lst
DATA/
подсправочник держит вышеупомянутую директивную структуру, то есть реальное
net.sw
материал и автоматически обновлен через
rdist
время от времени. Вторая часть проблемы остается: как соединять эти две структуры в одно гладко-выглядящее дерево URL? Мы хотим скрыться
DATA/
справочник от пользователя, при управлении соответствующих подлинников CGI для различных URL. Вот - решение: сначала я помещал следующее во в-справочник файл конфигурации в
DocumentRoot
из сервера, чтобы переписать объявленный URL
/net.sw/
к внутренней дорожке
/e/netsw
:
RewriteRule ^net.sw$ net.sw/ [R] RewriteRule ^net.sw/(.*)$ e/netsw/$1
первое правило - для запросов, которые пропускают тянущийся разрез! Второе правило делает реальную вещь. И затем прибывает конфигурация убийцы, которая остается во в-справочник config файле
/e/netsw/.www/.wwwacl
:
Options ExecCGI FollowSymLinks Includes MultiViews RewriteEngine on # we are reached via /net.sw/ prefix RewriteBase /net.sw/ # first we rewrite the root dir to # the handling cgi script RewriteRule ^$ netsw-home.cgi [L] RewriteRule ^index\.html$ netsw-home.cgi [L] # strip out the subdirs when # the browser requests us from perdir pages RewriteRule ^.+/(netsw-[^/]+/.+)$ $1 [L] # and now break the rewriting for local files RewriteRule ^netsw-home\.cgi.* - [L] RewriteRule ^netsw-changes\.cgi.* - [L] RewriteRule ^netsw-search\.cgi.* - [L] RewriteRule ^netsw-tree\.cgi$ - [L] RewriteRule ^netsw-about\.html$ - [L] RewriteRule ^netsw-img/.*$ - [L] # anything else is a subdir which gets handled # by another cgi script RewriteRule !^netsw-lsdir\.cgi.* - [C] RewriteRule (.*) netsw-lsdir.cgi/$1
некоторые намеки для интерпретации:
L
(последний) флаг и никакая область замены ('
-
') в дальше часть
!
(не) характер и
C
(цепь) флаг при первом правиле в последней части
mod_imap
переключение от NCSA webserver к более современному Apacheскому webserver много людей хочет гладкий переход. Таким образом они хотят страницы, которые используют их старый NCSA
imagemap
программа, чтобы работать под Apache с современным
mod_imap
. проблема состоит в том, что есть много из, осуществляет гиперссылку вокруг который ссылка
imagemap
программа через
/cgi-bin/imagemap/path/to/page.map
. под Apache это должно читать только
/path/to/page.map
.
мы используем глобальное правило удалить приставку, непрерывную для всех запросов:
RewriteEngine on RewriteRule ^/cgi-bin/imagemap(.*) $1 [PT]
иногда необходимо позволить поиску webserver страниц в больше чем одном справочнике. Здесь Мультирассматривает, или другие методы не могут помочь.
мы программируем явный ruleset, который ищет файлы в справочниках.
RewriteEngine on # first try to find it in custom/... # ...and if found stop and be happy: RewriteCond /your/docroot/ dir1 /%{REQUEST_FILENAME} -f RewriteRule ^(.+) /your/docroot/ dir1 /$1 [L] # second try to find it in pub/... # ...and if found stop and be happy: RewriteCond /your/docroot/ dir2 /%{REQUEST_FILENAME} -f RewriteRule ^(.+) /your/docroot/ dir2 /$1 [L] # else go on for other Alias or ScriptAlias directives, # etc. RewriteRule ^(.+) - [PT]
возможно Вы хотите держать информацию статуса между запросами и использовать URL, чтобы закодировать это. Но Вы не хотите использовать обертку CGI для всех страниц только, чтобы раздеть эту информацию.
мы используем переписывающееся правило раздеть информацию статуса и помнить это через переменную окружающей среды, которая может быть более поздним dereferenced изнутри XSSI или CGI. Этим путем URL
/foo/S=java/bar/
переведен к
/foo/bar/
и названная переменная окружающей среды
STATUS
собирается ценность "Ява".
RewriteEngine on RewriteRule ^(.*)/ S=([^/]+) /(.*) $1/$3 [E= STATUS:$2 ]
предположить, что Вы хотите обеспечить
www.
username
.host.domain.com
для начальной страницы имени пользователя через справедливый DNS отчеты на ту же самую машину и без любого virtualhosts на этой машине.
для запросов HTTP/1.0 нет никакого решения, но для запросов HTTP/1.1, которые содержат Хозяина: удар головой HTTP мы можем использовать следующий ruleset, чтобы переписать
http://www.username.host.com/anypath
внутренне к
/home/username/anypath
:
RewriteEngine on RewriteCond %{ HTTP_HOST } ^www\. [^.]+ \.host\.com$ RewriteRule ^(.+) %{HTTP_HOST}$1 [C] RewriteRule ^www\. ([^.]+) \.host\.com(.*) /home/ $1 $2
мы хотим переадресовать homedir URL к другому webserver
www.somewhere.com
когда пользователь требования не остается в местной области
ourdomain.com
. это иногда используется в действительных контекстах хозяина.
только переписывающееся условие:
RewriteEngine on RewriteCond %{REMOTE_HOST} !^.+\.ourdomain\.com$ RewriteRule ^(/~.+) http://www.somewhere.com/$1 [R,L]
типичные ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ о переписывании URL - как переадресовать запросы провала попытки на webserver к webserver B. Обычно это сделано через
ErrorDocument
CGI-подлинники в Perl, но есть также a
mod_rewrite
решение. Но уведомление, которое это выполняет более плохо чем использование
ErrorDocument
CGI-подлинник!
первое решение имеет лучшую работу, но меньше гибкости, и - меньше ошибочного сейфа:
RewriteEngine on RewriteCond /your/docroot/%{REQUEST_FILENAME} !-f RewriteRule ^(.+) http:// webserverB .dom/$1
проблема здесь состоит в том, что это будет только работать для страниц в
DocumentRoot
. в то время как Вы можете добавить больше Условий (например, чтобы также обращаться с homedirs, и т.д.) есть лучший вариант:
RewriteEngine on RewriteCond %{REQUEST_URI} !-U RewriteRule ^(.+) http:// webserverB .dom/$1
это использует особенность предвидения URL
mod_rewrite
. результат состоит в том, что это будет работать для всех типов URL и - безопасный путь. Но это делает воздействие работы на webserver, потому что для каждого запроса есть еще один внутренний подзапрос. Так, если ваши пробеги webserver на мощном центральном процессоре, используйте этот. Если это - медленная машина, используйте первый подход или лучше a
ErrorDocument
CGI-подлинник.
иногда мы нуждаемся в большем количестве контроля (относительно характера, избегающего механизма) URL на, переадресовывает. Обычно Apache функция спасения URL ядер также избегает якорей, то есть. URL как "
url#anchor
". Вы не можете использовать, это непосредственно на переадресовывает с
mod_rewrite
потому что
uri_escape()
функция Apacheа также избежала бы характера мешанины. Как мы можем переадресовать к такому URL?
мы должны использовать клудж при помощи подлинника NPH-CGI, который делает переадресовывание. Поскольку здесь никакая возможность избежать не сделана (NPH=non-parseable удары головой). Сначала мы вводим новую схему URL
xredirect:
следующей в-сервер config-линией (должен быть один из последних, переписывают правила):
RewriteRule ^xredirect:(.+) /path/to/nph-xredirect.cgi/$1 \ [T=application/x-httpd-cgi,L]
это вызывает все URL, предустановленные с
xredirect:
заканчивать piped
nph-xredirect.cgi
программа. И эта программа только похожа:
#!/path/to/perl ## ## nph-xredirect.cgi -- NPH/CGI script for extended redirects ## Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved. ## $| = 1; $url = $ENV{'PATH_INFO'}; print "HTTP/1.0 302 Moved Temporarily\n"; print "Server: $ENV{'SERVER_SOFTWARE'}\n"; print "Location: $url\n"; print "Content-type: text/html\n"; print "\n"; print "<html>\n"; print "<head>\n"; print "<title>302 Moved Temporarily (EXTENDED)</title>\n"; print "</head>\n"; print "<body>\n"; print "<h1>Moved Temporarily (EXTENDED)</h1>\n"; print "The document has moved <a HREF=\"$url\">here</a>.<p>\n"; print "</body>\n"; print "</html>\n"; ##EOF##
это предоставляет, Вы с функциональными возможностями, чтобы сделать переадресовываете ко всем схемам URL, то есть включая тот, которые непосредственно не приняты
mod_rewrite
. например Вы можете теперь также переадресовать к
news:newsgroup
через
RewriteRule ^anyurl xredirect:news:newsgroup
[R]
или
[R,L]
к вышеупомянутому правилу, потому что
xredirect:
должен быть расширен позже нашей специальной "трубой через" правило выше.
сделать Вы знаете большой CPAN (Всесторонняя Сеть Архива Perl) под
http://www.perl.com/CPAN
? Это делает переадресовывание к одному из нескольких серверов ПРОГРАММЫ ПЕРЕДАЧИ ФАЙЛОВ во всем мире, которые несут зеркало CPAN, и - приблизительно около местоположения клиента требования. Фактически это можно назвать обслуживанием мультиплексирования доступа ПРОГРАММЫ ПЕРЕДАЧИ ФАЙЛОВ. В то время как CPAN бежит через подлинники CGI, как может подобный подход, осуществленный через
mod_rewrite
?
сначала мы замечаем это от версии 3.0.0
mod_rewrite
может также использовать "
ftp:
"схема на переадресовывает. И секунда, приближение местоположения может быть сделано a
RewriteMap
по высокопоставленной области клиента. С прикованным ruleset хитрого мы можем использовать эту высокопоставленную область как ключ к нашей карте мультиплексирования.
RewriteEngine on RewriteMap multiplex txt:/path/to/map.cxan RewriteRule ^/CxAN/(.*) %{REMOTE_HOST}::$1 [C] RewriteRule ^.+\. ([a-zA-Z]+) ::(.*)$ ${multiplex: $1 |ftp.default.dom}$2 [R,L]
## ## map.cxan -- Multiplexing Map for CxAN ## de ftp://ftp.cxan.de/CxAN/ uk ftp://ftp.cxan.uk/CxAN/ com ftp://ftp.cxan.com/CxAN/ : ##EOF##
когда уловки как зависимое временем содержание должны случиться, что много webmasters все еще использует подлинники CGI, которые делают например переадресовывает к специализированным страницам. Как может это быть сделанным через
mod_rewrite
?
есть много названных переменных
TIME_xxx
для переписывают условия. В соединении со специальными лексикографическими образцами сравнения
<STRING
,
>STRING
и
=STRING
мы можем сделать иждивенец времени переадресовывает:
RewriteEngine on RewriteCond %{TIME_HOUR}%{TIME_MIN} >0700 RewriteCond %{TIME_HOUR}%{TIME_MIN} <1900 RewriteRule ^foo\.html$ foo.day.html RewriteRule ^foo\.html$ foo.night.html
это обеспечивает содержание
foo.day.html
под URL
foo.html
от
07:00-19:00
и в остающееся время содержание
foo.night.html
. только хорошая особенность начальной страницы...
как может мы делать URL назад совместимыми (все еще существующий фактически) после перемещения
document.YYYY
к
document.XXXX
, например после перевода связки
.html
файлы к
.phtml
?
мы только переписываем название к его basename и тесту на существование нового расширения. Если это существует, мы берем то название, еще мы переписываем URL к его оригинальному государству.
# backward compatibility ruleset for # rewriting document.html to document.phtml # when and only when document.phtml exists # but no longer document.html RewriteEngine on RewriteBase /~quux/ # parse out basename, but remember the fact RewriteRule ^(.*)\.html$ $1 [C,E=WasHTML:yes] # rewrite to document.phtml if exists RewriteCond %{REQUEST_FILENAME}.phtml -f RewriteRule ^(.*)$ $1.phtml [S=1] # else reverse the previous basename cutout RewriteCond %{ENV:WasHTML} ^yes$ RewriteRule ^(.*)$ $1.html
предположить, что мы недавно переименовали страницу
foo.html
к
bar.html
и теперь хотите обеспечить старый URL для обратной совместимости. Фактически мы хотим это, пользователи старого URL даже не признают, что страницы были переименованы.
мы переписываем старый URL к новому внутренне через следующее правило:
RewriteEngine on RewriteBase /~quux/ RewriteRule ^ foo \.html$ bar .html
предположить снова, что мы недавно переименовали страницу
foo.html
к
bar.html
и теперь хотите обеспечить старый URL для обратной совместимости. Но на сей раз мы хотим это, пользователям старого URL намекают новому, то есть их область Location браузеров должна измениться, также.
мы вызываем HTTP, переадресовывают к новому URL, который приводит к изменению браузеров и таким образом представление пользователей:
RewriteEngine on RewriteBase /~quux/ RewriteRule ^ foo \.html$ bar .html [ R ]
по крайней мере для важных высокопоставленных страниц иногда необходимо обеспечить оптимум содержания иждивенца браузера, то есть каждый должен обеспечить максимальную версию для последних вариантов Netscape, минимальная версия для браузеров Рыси и средней версии особенности для всех других.
мы не можем использовать довольные переговоры, потому что браузеры не обеспечивают их тип в той форме. Вместо этого мы должны действовать на удар головой HTTP "Пользовательский агент". Следующий condig делает следующее: Если удар головой HTTP "Пользовательский агент" начинается с "Mozilla/3", страницы
foo.html
переписан к
foo.NS.html
и и остановки переписывания. Если браузер - "Рысь" или "Mozilla" версии 1 или 2, URL становится
foo.20.html
. все другие браузеры получают страницу
foo.32.html
. это сделано следующим ruleset:
RewriteCond %{HTTP_USER_AGENT} ^ Mozilla/3 .* RewriteRule ^foo\.html$ foo. NS .html [ L ] RewriteCond %{HTTP_USER_AGENT} ^ Lynx/ .* [OR] RewriteCond %{HTTP_USER_AGENT} ^ Mozilla/[12] .* RewriteRule ^foo\.html$ foo. 20 .html [ L ] RewriteRule ^foo\.html$ foo. 32 .html [ L ]
предположить, что есть хорошие webpages на отдаленных хозяевах, которых мы хотим принести в наш namespace. Для серверов ПРОГРАММЫ ПЕРЕДАЧИ ФАЙЛОВ мы использовали бы
mirror
программа, которая фактически поддерживает явную современную копию отдаленных данных относительно местной машины. Для webserver мы могли использовать программу
webcopy
который действует подобный через HTTP. Но оба метода имеют один главный недостаток: местная копия всегда столь же современна как часто, мы управляем программой. Было бы намного лучше, если зеркало не статический, мы должны установить явно. Вместо этого мы хотим динамическое зеркало с данными, которые обновлены автоматически, когда есть потребность (обновленные данные относительно отдаленного хозяина).
чтобы обеспечивать эту особенность, мы наносим на карту отдаленный webpage или даже полный отдаленный webarea к нашему namespace при помощи
Пропускная способность По доверенности
особенность (флаг
[P]
):
RewriteEngine on RewriteBase /~quux/ RewriteRule ^ hotsheet/ (.*)$ http://www.tstimpreso.com/hotsheet/ $1 [ P ]
RewriteEngine on RewriteBase /~quux/ RewriteRule ^ usa-news\.html $ http://www.quux-corp.com/news/index.html [ P ]
RewriteEngine on RewriteCond /mirror/of/remotesite/$1 -U RewriteRule ^http://www\.remotesite\.com/(.*)$ /mirror/of/remotesite/$1
это - хитрый путь действительного управления корпоративным (внешним) Интернетом webserver (
www.quux-corp.dom
), фактически держа и поддержание его данных относительно (внутреннего) Интранета webserver (
www2.quux-corp.dom
), который защищен брандмауэром. Уловка - то, что на внешнем webserver мы восстанавливаем требуемые данные, непрерывные от внутреннего.
сначала, мы должны удостовериться, что наш брандмауэр все еще защищает внутренний webserver и что только внешнему webserver позволяют восстановить данные от этого. Для фильтрующего пакет брандмауэра мы могли например формировать брандмауэр ruleset как следующее:
ALLOW Host www.quux-corp.dom Port >1024 --> Host www2.quux-corp.dom Port 80 DENY Host * Port * --> Host www2.quux-corp.dom Port 80
только приспособьте это к вашему фактическому синтаксису конфигурации. Теперь мы можем установить
mod_rewrite
правила, которые просят недостающие данные на заднем плане через особенность пропускной способности по доверенности:
RewriteRule ^/~([^/]+)/?(.*) /home/$1/.www/$2 RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^/home/([^/]+)/.www/?(.*) http:// www2 .quux-corp.dom/~$1/pub/$2 [ P ]
предположим, что мы хотим загрузить баланс движение к
www.foo.com
www[0-5].foo.com
(в общей сложности 6 серверов). Как это может быть сделано?
есть много возможных решений для этой проблемы. Мы обсудим сначала обычно известный DNS-базирующийся вариант и затем специальный с
mod_rewrite
:
самый простой метод для балансирования груза должен использовать особенность коллективного письма DNS
BIND
. здесь Вы только формируете
www[0-9].foo.com
как обычно в вашем DNS с (адрес) отчеты, например.
www0 IN A 1.2.3.1 www1 IN A 1.2.3.2 www2 IN A 1.2.3.3 www3 IN A 1.2.3.4 www4 IN A 1.2.3.5 www5 IN A 1.2.3.6
тогда Вы дополнительно добавляете следующий вход:
www IN CNAME www0.foo.com. IN CNAME www1.foo.com. IN CNAME www2.foo.com. IN CNAME www3.foo.com. IN CNAME www4.foo.com. IN CNAME www5.foo.com. IN CNAME www6.foo.com.
заметить, что это кажется неправильным, но - фактически намеченная особенность
BIND
и может использоваться таким образом. Однако, теперь когда
www.foo.com
решен,
BIND
выделяет
www0-www6
- но в немного permutated/rotated заказывают каждый раз. Этим путем клиенты распространены по различным серверам. Но уведомление, что это не прекрасный груз, уравновешивающий схему, потому что DNS решают информацию, прячется про запас другим nameservers на сети, так однажды клиент, решило
www.foo.com
к детали
wwwN.foo.com
, все последующие запросы также идут в это специфическое название
wwwN.foo.com
. но заключительный результат в порядке, потому что полная сумма запросов действительно распространяется по различному webservers.
сложный DNS-базирующийся метод для балансирования груза должен использовать программу
lbnamed
который может быть найден в
http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html
. это - Perl 5 программ в соединении с auxilliary инструментами, которое обеспечивает реальное балансирование груза для DNS.
в этом варианте мы используем
mod_rewrite
и его особенность пропускной способности по доверенности. Сначала мы посвящаем
www0.foo.com
быть фактически
www.foo.com
при использовании единственного
www IN CNAME www0.foo.com.
вход в DNS. Тогда мы преобразовываем
www0.foo.com
к серверу только для полномочия, то есть мы формируем эту машину, таким образом все прибывающие URL только выдвинуты через внутреннее полномочие к одному из 5 других серверов (
www1-www5
). Чтобы достигать этого, мы сначала устанавливаем ruleset, который связывается с грузом, уравновешивающим подлинник
lb.pl
для всех URL.
RewriteEngine on RewriteMap lb prg:/path/to/lb.pl RewriteRule ^/(.+)$ ${lb:$1} [P,L]
тогда мы пишем
lb.pl
:
#!/path/to/perl ## ## lb.pl -- load balancing script ## $| = 1; $name = "www"; # the hostname base $first = 1; # the first server (not 0 here, because 0 is myself) $last = 5; # the last server in the round-robin $domain = "foo.dom"; # the domainname $cnt = 0; while (<STDIN>) { $cnt = (($cnt+1) % ($last+1-$first)); $server = sprintf("%s%d.%s", $name, $cnt+$first, $domain); print "http://$server/$_"; } ##EOF##
www0.foo.com
все еще перегружается? Ответ да, это перегружено, но с простыми запросами пропускной способности по доверенности, только! Вся ПЕРВАЯ СТЕПЕНЬ ИНТЕГРАЦИИ, CGI, ePerl, и т.д. обработка полностью сделана на других машинах. Это - существенный пункт.
есть доступное решение для аппаратных средств, также. Cisco имеет животное по имени LocalDirector, который делает груз, балансирующий на уровне TCP/IP. Фактически это - своего рода ворота уровня кругооборота перед webcluster. Если Вы имеете достаточно денег и действительно нуждаетесь в решении с высокой эффективностью, используете этот.
на сети есть много изящных программ CGI. Но их использование обычно скучно, таким образом много webmaster не использует их. Даже особенность тренера Действия Апача ТИПОВ ПАНТОМИМЫ является только соответствующей, когда программы CGI не нуждаются в специальных URL (фактически
PATH_INFO
и
QUERY_STRINGS
) как их вход. Сначала, позвольте нам формировать новый тип файла с расширением
.scgi
(для безопасного CGI), который будет обработан популярным
cgiwrap
программа. Проблема здесь состоит в том, что например мы используем Гомогенное Расположение URL (см. выше), файл в пользовательском homedirs имеет URL
/u/user/foo/bar.scgi
. но
cgiwrap
нуждается в URL в форме
/~user/foo/bar.scgi/
. следующее правило решает проблему:
RewriteRule ^/[uge]/ ([^/]+) /\.www/(.+)\.scgi(.*) ... ... /internal/cgi/user/cgiwrap/~ $1 /$2.scgi$3 [NS, T=application/x-http-cgi ]
или предположите, что мы имеем еще некоторые изящные программы:
wwwlog
(который показывает
access.log
для поддерева URL и
wwwidx
(который управляет Проблеском на поддереве URL). Мы должны обеспечить область URL к этим программам, таким образом они знают, на какой области они должны действовать на. Но обычно это уродливый, потому что они - все времена, все еще которые требуют от этого области, то есть типично мы бежали бы
swwidx
программа изнутри
/u/user/foo/
через гиперссылку к
/internal/cgi/user/swwidx?i=/u/user/foo/
который является уродливым. Поскольку мы имеем к твердому кодексу оба местоположение области и местоположение CGI в гиперссылке. То, когда мы должны реорганизовать область, мы тратим много времени изменение различного, осуществляет гиперссылку.
решение здесь состоит в том, чтобы обеспечить специальный новый формат URL, который автоматически приводит к надлежащей просьбе CGI. Мы формируем следующее:
RewriteRule ^/([uge])/([^/]+)(/?.*)/\* /internal/cgi/user/wwwidx?i=/$1/$2$3/ RewriteRule ^/([uge])/([^/]+)(/?.*):log /internal/cgi/user/wwwlog?f=/$1/$2$3
теперь гиперссылка, чтобы искать в
/u/user/foo/
читает только
HREF="*"
который внутренне автоматически преобразован к
/internal/cgi/user/wwwidx?i=/u/user/foo/
тот же самый подход приводит к просьбе для регистрации доступа программа CGI когда гиперссылка
:log
привыкает.
как может мы преобразовывать статическую страницу
foo.html
в динамический вариант
foo.cgi
способом без шва, то есть без уведомления браузером/пользователем.
мы только переписываем URL к CGI-подлиннику и вызываем правильный ТИП ПАНТОМИМЫ, таким образом этим действительно управляют как CGI-подлинник. Этим путем запрос к
/~quux/foo.html
внутренне приводит к просьбе
/~quux/foo.cgi
.
RewriteEngine on RewriteBase /~quux/ RewriteRule ^foo\. html $ foo. cgi [T= application/x-httpd-cgi ]
здесь прибывает действительно тайная особенность: Динамически произведенные но страницы, которым статически служат, то есть страницы нужно поставить как чистые статические страницы (прочитанный от файловой системы, и только прошел), но они должны быть произведены динамически webserver, отсутствуя. Этим путем Вы могли CGI-произвести страницы, которым статически служат, если один (или cronjob) не удаляет статическое содержание. Тогда содержание освежено.
RewriteCond %{REQUEST_FILENAME} !-s RewriteRule ^page\. html $ page. cgi [T=application/x-httpd-cgi,L]
здесь запрос к
page.html
приводит к внутреннему пробегу передачи
page.cgi
если
page.html
все еще пропускает или имеет filesize пустой указатель. Уловка здесь - это
page.cgi
является обычным подлинником CGI который (дополнительно к
STDOUT
) пишет его продукция файлу
page.html
. как только этим управляли, сервер отсылает данные
page.html
. когда webmaster хочет вызвать освежение содержания, он только удаляет
page.html
(обычно сделанный cronjob).
разве это не было бы хорошо, создавая комплекс webpage, если webbrowser автоматически освежит страницу каждый раз, мы пишем новую версию изнутри нашего редактора? Невозможный?
нет! Мы только комбинируем ПАНТОМИМУ многослойная особенность, webserver NPH особенность и власть манипуляции URL
mod_rewrite
. сначала, мы устанавливаем новую особенность URL: Добавление только
:refresh
к любым причинам URL это, чтобы быть освежен каждый раз это обновлено на файловой системе.
RewriteRule ^(/[uge]/[^/]+/?.*):refresh /internal/cgi/apache/nph-refresh?f=$1
теперь, когда мы ссылаемся на URL
/u/foo/bar/page.html:refresh
это приводит к внутренней просьбе URL
/internal/cgi/apache/nph-refresh?f=/u/foo/bar/page.html
единственная недостающая часть - подлинник NPH-CGI. Хотя можно было бы обычно говорить "оставленный как осуществление читателю" ;-), я обеспечу этому, также.
#!/sw/bin/perl ## ## nph-refresh -- NPH/CGI script for auto refreshing pages ## Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved. ## $| = 1; # split the QUERY_STRING variable @pairs = split(/&/, $ENV{'QUERY_STRING'}); foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $name =~ tr/A-Z/a-z/; $name = 'QS_' . $name; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; eval "\$$name = \"$value\""; } $QS_s = 1 if ($QS_s eq ''); $QS_n = 3600 if ($QS_n eq ''); if ($QS_f eq '') { print "HTTP/1.0 200 OK\n"; print "Content-type: text/html\n\n"; print "<b>ERROR</b>: No file given\n"; exit(0); } if (! -f $QS_f) { print "HTTP/1.0 200 OK\n"; print "Content-type: text/html\n\n"; print "<b>ERROR</b>: File $QS_f not found\n"; exit(0); } sub print_http_headers_multipart_begin { print "HTTP/1.0 200 OK\n"; $bound = "ThisRandomString12345"; print "Content-type: multipart/x-mixed-replace;boundary=$bound\n"; &print_http_headers_multipart_next; } sub print_http_headers_multipart_next { print "\n--$bound\n"; } sub print_http_headers_multipart_end { print "\n--$bound--\n"; } sub displayhtml { local($buffer) = @_; $len = length($buffer); print "Content-type: text/html\n"; print "Content-length: $len\n\n"; print $buffer; } sub readfile { local($file) = @_; local(*FP, $size, $buffer, $bytes); ($x, $x, $x, $x, $x, $x, $x, $size) = stat($file); $size = sprintf("%d", $size); open(FP, "<$file"); $bytes = sysread(FP, $buffer, $size); close(FP); return $buffer; } $buffer = &readfile($QS_f); &print_http_headers_multipart_begin; &displayhtml($buffer); sub mystat { local($file) = $_[0]; local($time); ($x, $x, $x, $x, $x, $x, $x, $x, $x, $mtime) = stat($file); return $mtime; } $mtimeL = &mystat($QS_f); $mtime = $mtime; for ($n = 0; $n < $QS_n; $n++) { while (1) { $mtime = &mystat($QS_f); if ($mtime ne $mtimeL) { $mtimeL = $mtime; sleep(2); $buffer = &readfile($QS_f); &print_http_headers_multipart_next; &displayhtml($buffer); sleep(5); $mtimeL = &mystat($QS_f); last; } sleep($QS_s); } } &print_http_headers_multipart_end; exit(0); ##EOF##
<VirtualHost>
особенность Apacheа хороша и большие работы, когда Вы только имеете несколько множеств действительных хозяев. Но когда Вы - ISP и имеете сотни действительных хозяев, чтобы обеспечить, эта особенность не лучший выбор.
чтобы обеспечивать эту особенность, мы наносим на карту отдаленный webpage или даже полный отдаленный webarea к нашему namespace при помощи
Пропускная способность По доверенности
особенность (флаг
[P]
):
## ## vhost.map ## www.vhost1.dom:80 /path/to/docroot/vhost1 www.vhost2.dom:80 /path/to/docroot/vhost2 : www.vhostN.dom:80 /path/to/docroot/vhostN
## ## httpd.conf ## : # use the canonical hostname on redirects, etc. UseCanonicalName on : # add the virtual host in front of the CLF-format CustomLog /path/to/access_log "%{VHOST}e %h %l %u %t \"%r\" %>s %b" : # enable the rewriting engine in the main server RewriteEngine on # define two maps: one for fixing the URL and one which defines # the available virtual hosts with their corresponding # DocumentRoot. RewriteMap lowercase int:tolower RewriteMap vhost txt:/path/to/vhost.map # Now do the actual virtual host mapping # via a huge and complicated single rule: # # 1. make sure we don't map for common locations RewriteCond %{REQUEST_URI} !^/commonurl1/.* RewriteCond %{REQUEST_URI} !^/commonurl2/.* : RewriteCond %{REQUEST_URI} !^/commonurlN/.* # # 2. make sure we have a Host header, because # currently our approach only supports # virtual hosting through this header RewriteCond %{HTTP_HOST} !^$ # # 3. lowercase the hostname RewriteCond ${lowercase:%{HTTP_HOST}|NONE} ^(.+)$ # # 4. lookup this hostname in vhost.map and # remember it only when it is a path # (and not "NONE" from above) RewriteCond ${vhost:%1} ^(/.*)$ # # 5. finally we can map the URL to its docroot location # and remember the virtual host for logging puposes RewriteRule ^/(.*)$ %1/$1 [E=VHOST:${lowercase:%{HTTP_HOST}}] :
как мы можем блокировать действительно раздражающий робот от восстановления страниц определенного webarea? A
/robots.txt
файл, содержащий записи "Протокола Исключения Робота" типично недостаточно, чтобы избавиться от такого робота.
мы используем ruleset, который запрещает URL webarea
/~quux/foo/arc/
(возможно очень глубокий справочник вносил область в указатель, где пересечение робота создаст большой груз сервера). Мы должны удостовериться, что мы запрещаем доступ только к специфическому роботу, то есть только запрещению хозяина, куда робот бежит - недостаточно. Это блокировало бы пользователей от этого хозяина, также. Мы достигаем этого, также соответствуя Пользовательскому агенту информация удара головой HTTP.
RewriteCond %{HTTP_USER_AGENT} ^ NameOfBadRobot .* RewriteCond %{REMOTE_ADDR} ^ 123\.45\.67\.[8-9] $ RewriteRule ^ /~quux/foo/arc/ .+ - [ F ]
предположить, что мы имеем под
http://www.quux-corp.de/~quux/
некоторые страницы с inlined графикой ДЖИФА. Эта графика хороша, таким образом другие, непосредственно включенный их через осуществляют гиперссылку к их страницам. Мы не любим эту практику, потому что это добавляет бесполезное движение к нашему серверу.
в то время как мы не можем 100 % защищать изображения от включения, мы можем по крайней мере ограничить случаи, куда браузер посылает HTTP Referer удар головой.
RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC] RewriteRule .*\.gif$ - [F]
RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !.*/foo-with-gif\.html$ RewriteRule ^inlined-in-foo\.gif$ - [F]
как мы можем запретить список внешне формируемых хозяев от использования нашего сервера?
для Apacheа >= 1.3b6:
RewriteEngine on RewriteMap hosts-deny txt:/path/to/hosts.deny RewriteCond ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND [OR] RewriteCond ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND RewriteRule ^/.* - [F]
для Apacheа <= 1.3b6:
RewriteEngine on RewriteMap hosts-deny txt:/path/to/hosts.deny RewriteRule ^/(.*)$ ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND}/$1 RewriteRule !^NOT-FOUND/.* - [F] RewriteRule ^NOT-FOUND/(.*)$ ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND}/$1 RewriteRule !^NOT-FOUND/.* - [F] RewriteRule ^NOT-FOUND/(.*)$ /$1
## ## hosts.deny ## ## ATTENTION! This is a map, not a list, even when we treat it as such. ## mod_rewrite parses it for key/value pairs, so at least a ## dummy value "-" must be present for each entry. ## 193.102.180.41 - bsdti1.sdm.de - 192.76.162.40 -
как мы можем запретить определенному хозяину или даже пользователь специального хозяина от использования Apacheского полномочия?
мы сначала должны удостовериться
mod_rewrite
является ниже (!)
mod_proxy
в файле Конфигурации, собирая Apache webserver. Этим путем это называют
прежде
mod_proxy
. тогда мы формируем следующее для хозяина-иждивенца, отрицают...
RewriteCond %{REMOTE_HOST} ^badhost\.mydomain\.com$ RewriteRule !^http://[^/.]\.mydomain.com.* - [F]
. .. и этот для user@host-dependent отрицают:
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} ^badguy@badhost\.mydomain\.com$ RewriteRule !^http://[^/.]\.mydomain.com.* - [F]
иногда очень специальное установление подлинности необходимо, например установление подлинности, которое проверяет для ряда явно формируемых пользователей. Только они должны получить доступ и без явного побуждения (который произошел бы, используя Основного Автора через
mod_auth
).
мы используем список, переписывают условия исключить все кроме наших друзей:
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend1@client1.quux-corp\.com$ RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend2 @client2.quux-corp\.com$ RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend3 @client3.quux-corp\.com$ RewriteRule ^/~quux/only-for-friends/ - [F]
как может мы программировать гибкий Дефлектор URL, который действует на "Referer" HTTP удар головой и может формироваться с так многими обратившимися страницами, как мы любим?
использовать следующий действительно хитрый ruleset...
RewriteMap deflector txt:/path/to/deflector.map RewriteCond %{HTTP_REFERER} !="" RewriteCond ${deflector:%{HTTP_REFERER}} ^-$ RewriteRule ^.* %{HTTP_REFERER} [R,L] RewriteCond %{HTTP_REFERER} !="" RewriteCond ${deflector:%{HTTP_REFERER}|NOT-FOUND} !=NOT-FOUND RewriteRule ^.* ${deflector:%{HTTP_REFERER}} [R,L]
. .. в соединении с передачей переписывают карту:
## ## deflector.map ## http://www.badguys.com/bad/index.html - http://www.badguys.com/bad/index2.html - http://www.badguys.com/bad/index3.html http://somewhere.com/
это автоматически переадресовывает запрос назад к обратившейся странице (когда "
-
"используется как ценность в карте), или к определенному URL (когда URL определен в карте как второй аргумент).
ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ: Как мы можем решить FOO/BAR/QUUX/etc. проблему? Там не кажется никаким решением при помощи
mod_rewrite
...
использовать внешнее
RewriteMap
, то есть программа, которая действует как a
RewriteMap
. этим управляют, как только на запуске Apacheа получает требуемые URL на
STDIN
и должен поместить окончание (обычно переписанный) URL на
STDOUT
(тот же самый заказ!).
RewriteEngine on RewriteMap quux-map prg: /path/to/map.quux.pl RewriteRule ^/~quux/(.*)$ /~quux/ ${quux-map:$1}
#!/path/to/perl # disable buffered I/O which would lead # to deadloops for the Apache server $| = 1; # read URLs one per line from stdin and # generate substitution URL on stdout while (<>) { s|^foo/|bar/|; print $_; }
это - пример только для демонстрации и только переписывает все URL
/~quux/foo/...
к
/~quux/bar/...
. фактически Вы можете программировать то, что Вы любите. Но уведомление, что, в то время как такие карты могут быть
используемый
также средним пользователем, только администратор системы может
определить
это.