Как закалялся код...: Настройка редиректов в nginx. Переадресация www.

суббота, 4 октября 2014 г.

Настройка редиректов в nginx. Переадресация www.

Настройка редиректов в nginx. Переадресация www | casterofcode.blogspot.ru
После переноса одного сайта на CSM Битрикс работающего на хостинге с apache на другой хостинг с вебсервером nginx, все правила в .htaccess стали непригодны. Благо их было не много. Разобравшись как и где прописать подобные правила для nginx, стандартное правило для скрипта обработки адресов 1C Битрикс (urlrewrite.php) нашел достаточно быстро:




.htaccess
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_FILENAME} !-l
 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteCond %{REQUEST_FILENAME} !/bitrix/urlrewrite.php$
 RewriteRule ^(.*)$ /bitrix/urlrewrite.php [L]

nginx.conf

f (!-e $request_filename) {
 rewrite  ^(.*)$ /bitrix/urlrewrite.php last;
}

На 2 других правила потратил времени чуть больше, т.к. найденные в сети примеры просто не работали или не подходили:
1. Редирект с поддомена www
2. Редирект с добавлением слэша "/" в конце строки при обращении к адресам без слеша.

Для настройки пришлось почитать документацию по nginx подробнее.

.htaccess


 #Remove 'www'
 RewriteCond %{HTTPS} !=on
 RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
 RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
 #Add '/'
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteCond %{REQUEST_URI} (.*/[^/.]+)($|\?)
 RewriteRule .* %1/ [R=301,L]


По www хотелось получить универсальное правило как было в .htaccess, не привязанное к названию конкретного домена. В итоге получил такой результат:

nginx.conf

#Remove 'www'
#Хост соответствует регулярному выражению
if ($http_host ~* "^www\.(.+)$"){

 #Запоминаем хост без www из предыдущего выражения в переменной $nowww
 set $nowww $1;


 #Делаем 301 редирект (permanent)
 #В $request_uri - адрес без хоста со всеми GET параметрами
 #После $request_uri добавляем '?' чтобы GET параметры
 #не добавились дважды (по умолчанию)
 rewrite ^ http://$nowww$request_uri? permanent;
}

#Add '/'
#Это не существующий файл/каталог...
if (!-e $request_filename){
 #301 редирект с добавлением '/'
 rewrite (.*/[^/.]+)($|\?) $1/ permanent;
}


В моем случае я просто вставил правила в нужные существующие директивы файла nginx.conf. Правила для nginx должны быть указаны внутри директивы конфигурации server:


server {
....
 if (!-e $request_filename){
   rewrite (.*/[^/.]+)($|\?) $1/ permanent;
 }
....
}

P.S. Полученного опыта недостаточно чтобы сравнивать apache и nginx. О плюсах и минусах можно найти материалы в сети, но один неудобный момент при использовании nginx.conf - нужно выполнять перезапуск сервиса nginx после каждого изменения конфигурации.

Bonus: Встроенные переменные nginx которые можно использовать при конфигурировании:

$args, эта переменная равна аргументам в строке запроса;
$arg_name, эта переменная равна аргументу name в строке запроса;
$binary_remote_addr, эта переменная равна адресу клиента в бинарном виде, длина её значения всегда 4 байта;
$content_length, эта переменная равна строке "Content-Length" в заголовке запроса;
$content_type, эта переменная равна строке "Content-Type" в заголовке запроса;
$cookie_name, эта переменная равна cookie name;
$document_root, эта переменная равна значению директивы root для текущего запроса;
$document_uri, то же самое, что и $uri;
$host, эта переменная равна строке "Host" в заголовке запроса или имени сервера, на который пришёл запрос, если этой строки нет;
$hostname, эта переменная равна имени хоста;
$http_name, эта переменная равна строке name в заголовке запроса;
$is_args, эта переменная равна "?", если в строке запроса есть аргументы, и пустой строке, если их нет;
$limit_rate, эта переменная позволяет установить ограничение скорости соединения;
$pid, эта переменная равна номеру рабочего процесса;
$request_method, эта переменная равна методу запроса, обычно это "GET" или "POST";
$remote_addr, эта переменная равна адресу клиента;
$remote_port, эта переменная равна порту клиента;
$remote_user, эта переменная равна имени пользователя, используемого в Basic аутентификации;
$realpath_root, эта переменная равна значению директивы root для текущего запроса, при этом все символические ссылки преобразованы в реальные путь;
$request_filename, эта переменная равна пути к файлу для текущего запроса, формируемому из директив root или alias и URI запроса;
$request_body, эта переменная содержит тело запроса. Значение переменной появляется в location'ах, обрабатываемых директивами proxy_pass и fastcgi_pass.
$request_body_file, эта переменная равна имени временного файла, в котором хранится тело запроса. По завершению работы файл необходимо удалить. Для того, чтобы тело запроса клиента всегда записывалось в файл, нужно указать client_body_in_file_only on. При передаче имени в проксированном запросе или в запросе к FastCGI-серверу следует запретить передачу самого тела директивами "proxy_pass_request_body off" или "fastcgi_pass_request_body off" соответственно.
$request_uri, эта переменная равна полному первоначальному URI вместе с аргументами;
$query_string, то же самое, что и $args;
$scheme, эта переменная равна схеме запроса — "http" или "https";
$server_protocol, эта переменная равна протоколу запроса, обычно это "HTTP/1.0" или "HTTP/1.1";
$server_addr, эта переменная равна адресу сервера, на который пришёл запрос. Как правило, для получения значения этой переменной делается один системный вызов. Для того, чтобы избежать системного вызова, нужно указывать адреса в директивах listen и использовать параметр bind;
$server_name, эта переменная равна имени сервера, на который пришёл запрос;
$server_port, эта переменная равна порту сервера, на который пришёл запрос;
$uri, эта переменная равна текущему URI в запросе, он может отличаться от первоначального, например, при внутренних редиректах или при использовании индексных файлов.

Комментариев нет:

Отправить комментарий