Как nginx обрабатывает запросы
| Как предотвратить обработку запросов без имени сервера Определение виртуального сервера по имени и IP-адресу Конфигурация простого сайта PHP | 
Определение виртуального сервера по имени
nginx вначале решает, какой из серверов должен обработать запрос. Рассмотрим простую конфигурацию, где все три виртуальных сервера слушают на порту *:80:
server {
    listen      80;
    server_name example.org www.example.org;
    ...
}
server {
    listen      80;
    server_name example.net www.example.net;
    ...
}
server {
    listen      80;
    server_name example.com www.example.com;
    ...
}
В этой конфигурации, чтобы определить, какому серверу следует направить
запрос, nginx проверяет только поле “Host” заголовка запроса.
Если его значение не соответствует ни одному из имён серверов
или в заголовке запроса нет этого поля вовсе,
nginx направит запрос в сервер по умолчанию для этого порта.
В вышеприведённой конфигурации сервером по умолчанию будет первый сервер,
что соответствует стандартному поведению nginx по умолчанию.
Сервер по умолчанию можно задать явно с помощью параметра
default_server в директиве
listen:
server {
    listen      80 default_server;
    server_name example.net www.example.net;
    ...
}
Параметрdefault_serverпоявился в версии 0.8.21. В более ранних версиях вместо него следует использовать параметрdefault.
Следует иметь в виду, что сервер по умолчанию является свойством слушающего порта, а не имени сервера. Подробнее это обсуждается ниже.
Как предотвратить обработку запросов без имени сервера
Если запросы без поля “Host” в заголовке не должны обрабатываться, можно определить сервер, который будет их отклонять:
server {
    listen      80;
    server_name "";
    return      444;
}
Здесь в качестве имени сервера указана пустая строка, которая соответствует запросам без поля “Host” в заголовке, и возвращается специальный для nginx код 444, который закрывает соединение.
Начиная с версии 0.8.48 настройка server_name ""
является стандартной и может явно не указываться.
В более ранних версиях в качестве стандартного имени сервера
выступало имя машины (hostname).
Определение виртуального сервера по имени и IP-адресу
Рассмотрим более сложную конфигурацию, в которой некоторые виртуальные серверы слушают на разных адресах:
server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}
server {
    listen      192.168.1.1:80;
    server_name example.net www.example.net;
    ...
}
server {
    listen      192.168.1.2:80;
    server_name example.com www.example.com;
    ...
}
 
В этой конфигурации nginx вначале сопоставляет IP-адрес и порт
запроса с директивами
listen
в блоках
server.
Затем он сопоставляет значение поля “Host”
заголовка запроса с директивами
server_name
в блоках
server,
которые соответствуют IP-адресу и порту.
Если имя сервера не найдено, запрос будет обработан в
сервере по умолчанию.
Например, запрос www.example.com, пришедший на порт
192.168.1.1:80, будет обработан сервером по умолчанию для порта
192.168.1.1:80, т.е. первым сервером, т.к. для этого порта
www.example.com не указан в списке имён серверов.
Как уже говорилось, сервер по умолчанию является свойством слушающего порта, поэтому у разных портов могут быть определены свои серверы по умолчанию:
server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}
server {
    listen      192.168.1.1:80 default_server;
    server_name example.net www.example.net;
    ...
}
server {
    listen      192.168.1.2:80 default_server;
    server_name example.com www.example.com;
    ...
}
Конфигурация простого сайта PHP
Теперь посмотрим на то, как nginx выбирает location для обработки запроса на примере обычного простого PHP-сайта:
server {
    listen      80;
    server_name example.org www.example.org;
    root        /data/www;
    location / {
        index   index.html index.php;
    }
    location ~* \.(gif|jpg|png)$ {
        expires 30d;
    }
    location ~ \.php$ {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME
                      $document_root$fastcgi_script_name;
        include       fastcgi_params;
    }
}
nginx вначале ищет среди всех префиксных location’ов, заданных строками,
максимально совпадающий.
В вышеприведённой конфигурации
указан только один префиксный location “/”, и поскольку
он подходит под любой запрос, он и будет использован, если других
совпадений не будет найдено.
Затем nginx проверяет location’ы, заданные регулярными выражениями, в
порядке их следования в конфигурационном файле.
При первом же совпадении поиск прекращается и nginx использует
совпавший location.
Если запросу не соответствует ни одно из регулярных выражений,
nginx использует максимально совпавший префиксный location,
найденный ранее.
Следует иметь в виду, что location’ы всех типов сопоставляются только с URI-частью строки запроса без аргументов. Так делается потому, что аргументы в строке запроса могут быть заданы различными способами, например:
/index.php?user=john&page=1 /index.php?page=1&user=john
Кроме того, в строке запроса можно запросить что угодно:
/index.php?page=1&something+else&user=john
Теперь посмотрим, как бы обрабатывались запросы в вышеприведённой конфигурации:
- 
Запросу “/logo.gif” во-первых соответствует префиксный location “/”, а во-вторых — регулярное выражение “\.(gif|jpg|png)$”, поэтому он обрабатывается location’ом регулярного выражения. Согласно директиве “root /data/www” запрос отображается в файл/data/www/logo.gif, который и посылается клиенту.
- 
Запросу “/index.php” также во-первых соответствует префиксный location “/”, а во-вторых — регулярное выражение “\.(php)$”. Следовательно, он обрабатывается location’ом регулярного выражения и запрос передаётся FastCGI-серверу, слушающему на localhost:9000. Директива fastcgi_param устанавливает FastCGI-параметрSCRIPT_FILENAMEв “/data/www/index.php”, и сервер FastCGI выполняет указанный файл. Переменная$document_rootравна значению директивы root, а переменная$fastcgi_script_nameравна URI запроса, т.е. “/index.php”.
- 
Запросу “/about.html” соответствует только префиксный location “/”, поэтому запрос обрабатывается в нём. Согласно директиве “root /data/www” запрос отображается в файл/data/www/about.html, который и посылается клиенту.
- 
Обработка запроса “/” более сложная. Ему соответствует только префиксный location “/”, поэтому запрос обрабатывается в нём. Затем директива index проверяет существование индексных файлов согласно своих параметров и директиве “root /data/www”. Если файл/data/www/index.htmlне существует, а файл/data/www/index.phpсуществует, то директива делает внутреннее перенаправление на “/index.php” и nginx снова сопоставляет его с location’ами, как если бы такой запрос был послан клиентом. Как мы видели ранее, перенаправленный запрос будет в конечном итоге обработан сервером FastCGI.
| автор: Игорь Сысоев редактор: Brian Mercer | 
