Идеальный
сайт выглядит одинаково во всех браузерах. Идеальный сайт выдает каждому
браузеру html-код, предназначенный именно для этого
браузера.
Если первое
утверждение не нуждается в пояснениях и доказательствах, то со вторым возникает
хитрый момент. С одной стороны, писать отдельный код под каждый браузер
утомительно, но с другой, — еще более утомительной может оказаться «тонкая
настройка» одного-единственного файла, чтобы он везде выглядел
одинаково.
Интересно, что второе
утверждение об идеальности сайта построено на неидеальности браузеров —
вели бы они себя одинаково, не пришлось бы писать разный код.
Что выбирать
— писать несколько файлов или пытаться создать переносимый код — решать кодеру.
Здесь рассказано о том, как настроить сервер, чтобы он самостоятельно выдавал
браузеру нужный файл. От веб-кодера при этом потребуется лишь создать несколько
вариантов файла и небольшую таблицу соответствия имен этих файлов нужным
браузерам.
Идею можно
развить, дополнив сайт специальными файлами для поисковых систем и удалив из
кода всю ненужную для поиска html-разметку. При этом размер файла скорее всего
заметно сократится. Текстовое содержание всех файлов должно совпадать, если вы
не преследуете иные цели.
Настройка
Apache
Для простоты
предположим, что все файлы на сайте — индексные, то есть адрес, по которому
пользователь запрашивает любой ресурс на сайте, оканчивается названием каталога.
Например, так: http://webcode.ru/cgi/browserdep/ .
Адреса
ресурсов при такой организации документов выглядят очень аккуратно, и скрывают
(до некоторой степени) детали реализации. Например, в адресах не будут видны
расширения файлов .shtml ,
.cgi ,
.php и так далее. Тем не
менее, описанная схема вполне допускает браузерозависимые отклики сервера на
файлы с любым расширением.
Чтобы не
осложнять напрасно работу веб-кодера разумно оставить возможность создания
единого файла для всех браузеров. Пусть этим файлом будет index.html . Если же необходимо
особое поведение для разных браузеров, создадим индексный файл
index.dep , в котором должна
быть записана таблица соответствий файлов браузеров. В том же каталоге следует
разместить несколько файлов, один из которых и будет выдан сервером в ответ на
запрос пользователя.
Веб-сервер
может самостоятельно определять, следует ли различать браузеры или нет — для
этого нужно записать в конфигурационный файл httpd.conf (или
.htaccess , чтобы изменения
подействовали только на текущий и вложенные каталоги) следующие
строки:
AddHandler dep-redir .dep
Action dep-redir /cgi-bin/dep-redir.pl
DirectoryIndex index.dep index.html
Инструкция
DirectoryIndex определяет порядок
поиска индексного файла. В том случае, если в каталоге окажется только файл
index.html , веб-сервер вернет
его пользователю безо всяких изменений. Если же в каталоге найдется файл
index.dep , сервер вызовет
обработчик с именем dep-redir , поскольку
инструкция AddHandler сопоставила его
расширению .dep . В свою очередь,
команда Action определяет, какая
программа отвечает за действия обработчика (это вовсе не обязательно должен быть
скрипт на Perl).
Таблица
соответствий
Файл
index.dep на самом деле не
содержит никакого html-кода. Вместо этого здесь записана таблица, которая ставит
в соответствие название браузера некоторому файлу с html-кодом. Если говорить
более точно, то в таблице записаны не названия браузеров, а регулярные
выражения, с которыми будет сопоставлено реальное имя.
Например,
файл зависимостей может выглядеть так (значения в строках разделены
табуляцией):
Opera index-op.html
MSIE index-ie.html
Netscapе index-nn.html
Mozilla index-mz.html
Lynx index-lx.html
Порядок
строк в этом файле имеет значение. Описанный далее обработчик остановится, как
только найдет первое подходящее название. Например, если удалить первую строку,
то для браузера Internet Explorer совпадет строка Mozilla . Строка
Netscape подойдет только для
Netscape 6 или 7. Если убрать и эту строку, все браузеры Netscape получат файл,
указанный в строке Mozilla .
Обработчик
Осталось
рассмотреть устройство обработчика, который будет вызван, если сервер обратится
к файлу index.dep . Все, что требуется
от обработчика, — узнать имя браузера (прочитав переменную $ENV{'HTTP_USER_AGENT'} ) и перенаправить
сервер на нужный файл (то есть напечатать http-заголовок, например, такой:
Location:
index-ie.html\n\n ).
Фактически
необходимо проделать некоторую дополнительную работу, чтобы определить каталог,
в котором находится запрошенный документ. Это можно сделать, отбросив часть
переменной $ENV{'REDIRECT_URL'} , начиная с
последнего слэша (удалив таким образом название индексного файла
index.dep ). Схожим образом
можно обработать и переменную $ENV{'PATH_INFO'} .
Найденное
имя каталога следует обязательно указать при печати http-заголовка. Таким
образом, реальный заголовок может иметь такой вид:
Location: /cgi/browserdep/index-ie.html\n\n
Поскольку в
поле Location указано имя
локального ресурса, перенаправление произойдет в пределах веб-сервера.
Пользователь получит нужный файл, но независимо от того, каким браузером он
пользуется, адресная строка останется неизменной (в данном случае
http://webcode.ru/cgi/browserdep/ ).
Пока еще
ничего не было сказано о чтении файла с таблицей зависимостей. Обработать его
довольно просто. Локальное имя файла (в файловой системе сервера) можно
определить из переменной $ENV{'PATH_TRANSLATED'} . Открыв файл, скрипт
построчно считывает его и проверяет, не совпало ли выражение в начале очередной
строки с названием браузера. После первого совпадения чтение файла-таблицы
останавливается и скрипт печатает соответствующий заголовок. Если же не найдено
ни одного совпадения, делается последняя попытка перенаправить сервер на
стандартный индексный файл index.html .
По этой
причине помимо файла index.dep на сервере
обязательно должен быть и файл index.html , несмотря на то, что
инструкции в конфигурационном файле Apache требуют наличия хотя бы одного из
них.
Полный
исходный код скрипта-обработчика выглядит так (в соответствии с записями в
конфигурационном файле этот скрипт следует сохранить под именем
dep-redir.pl и поместить в
каталог /cgi-bin/ ):
#!/usr/bin/perl
my $user_agent = $ENV{'HTTP_USER_AGENT'};
my ($dir) = ($ENV{'REDIRECT_URL'} =~ m/(.*\/)[^\/]+$/);
my $file = $ENV{'PATH_TRANSLATED'};
my $ret = "";
open DEP_REDIR, $file;
foreach my $rule (<DEP_REDIR>)
{
my ($pattern, $redir) = split (/\t/, $rule);
if ($user_agent =~ m/$pattern/i)
{
$realfile = "$redir";
last;
}
}
close DEP_REDIR;
$realfile = "index.html" unless $realfile;
print "Location: $dir$realfile\n\n";
|