Это действительно очень сложный пример: серьёзная вещь, очень интенсивно использующая RewriteRules
в контексте каталогов(.htaccess) для того, чтобы получить приятный вид данных и и при просмотре их через интернет чувство того, что структура данных никогда не трогается или регулируется. Предыстория: 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 скрипты на её верх. Почему? Потому что вышеприведённая структура позже должна была быть доступна также и через FTP, и я не хотел наличия там каких-либо веб или CGI штук.
Решение состоит из 2-х частей: Первое — это набор 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
Первое правило предназначено для запросов у который отсутствует завершающий слэш! Второе правило делает нужное преобразование. И затем, в конфигурационном файле каталога /e/netsw/.www/.wwwacl
, производится полное конфигурирование:
Options ExecCGI FollowSymLinks Includes MultiViews
RewriteEngine on
# устанавливем префикс /net.sw/
RewriteBase /net.sw/
# сначала мы перенаправляем все запросы к корневому каталогу на
# управляющий cgi скрипт
RewriteRule ^$ netsw-home.cgi [L]
RewriteRule ^index\.html$ netsw-home.cgi [L]
# обрезаем подкаталоги когда
# браузер запрашивает нас со страниц в подкаталогах
RewriteRule ^.+/(netsw-[^/]+/.+)$ $1 [L]
# и теперь не делаем редирект для локальных файлов
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]
# все остальное является подкаталогом и управляется
# другим cgi скриптом
RewriteRule !^netsw-lsdir\.cgi.* - [C]
RewriteRule (.*) netsw-lsdir.cgi/$1
Некоторые советы по интерпретации:
- Отметьте флаг
L
(последний) и отсутствие поля подстановки ('-
') в 4-й части
- Отметьте символ
!
(не) и флаг C
(цепочка) в первом правиле последней части
- Отметьте шаблон перехватывающий все запросы в последнем правиле