- Как nginx обрабатывает запрос
- Как предотвратить обработку запросов с неопределенными именами серверов
- Смешанные виртуальные серверы,основанные на именах и IP-адресах
- Простая настройка PHP-сайта
- Как предотвратить обработку запросов без имени сервера
- Определение виртуального сервера по имени и IP-адресу
- Конфигурация простого сайта PHP
Как nginx обрабатывает запрос
nginx сначала решает,какой server должны обрабатывать запрос.Начнем с простой конфигурации,в которой все три виртуальных сервера прослушивают порт *: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 блоков сервера . Затем он проверяет поле заголовка «Host» запроса на соответствие записям server_name блоков сервера , которые соответствуют 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 сначала ищет наиболее конкретное расположение префикса, заданное литеральными строками, независимо от порядка в списке. В приведенной выше конфигурации единственным расположением префикса является « / », и, поскольку он соответствует любому запросу, он будет использоваться в крайнем случае. Затем nginx проверяет местоположения, заданные регулярным выражением, в порядке, указанном в файле конфигурации. Первое совпадающее выражение останавливает поиск, и nginx будет использовать это местоположение. Если ни одно регулярное выражение не соответствует запросу, то nginx использует наиболее точное местоположение префикса, найденное ранее.
Обратите внимание,что локации всех типов проверяют только часть строки запроса URI без аргументов.Это делается потому,что аргументы в строке запроса могут быть заданы несколькими способами,например:
/index.php?user=john&page=1 /index.php?page=1&user=john
Кроме того,любой может запросить что угодно в строке запроса:
/index.php?page=1&something+else&user=john
Теперь давайте посмотрим,как будут обрабатываться запросы в приведенной выше конфигурации:
- Запрос « /logo.gif » сначала соответствует местоположению префикса « / », а затем регулярному выражению « \.(gif|jpg|png)$ », поэтому он обрабатывается по последнему местоположению. С помощью директивы « root /data/www » запрос сопоставляется с файлом /data/www/logo.gif , и этот файл отправляется клиенту.
- Запрос « /index.php » также сначала соответствует местоположению префикса « / », а затем регулярному выражению « \.(php)$ ». Поэтому он обрабатывается последним местом, и запрос передается на сервер FastCGI, который прослушивает localhost:9000. Директива fastcgi_param устанавливает для параметра FastCGI SCRIPT_FILENAME значение « /data/www/index.php », и сервер FastCGI выполняет файл. Переменная $document_root равна значению корневой директивы, а переменная $fastcgi_script_name соответствует URI запроса, т.е. « /index.php ».
- Запрос « /about.html » соответствует только местоположению префикса « / », поэтому он обрабатывается в этом месте. С помощью директивы « root /data/www » запрос сопоставляется с файлом /data/www/about.html , и этот файл отправляется клиенту.
- Обработка запроса « / » более сложная. Он соответствует только местоположению префикса « / », поэтому он обрабатывается этим расположением. Затем директива index проверяет наличие индексных файлов в соответствии со своими параметрами и директивой « root /data/www ». Если файл /data/www/index.html не существует, а файл /data/www/index.php существует, то директива выполняет внутреннее перенаправление на « /index.php », и nginx снова ищет местоположения как если запрос был отправлен клиентом. Как мы видели ранее, перенаправленный запрос в конечном итоге будет обработан сервером FastCGI.
nginx 1.23
Модуль ngx_http_v2_module (1.9.5) обеспечивает поддержку HTTP/2 и заменяет модуль ngx_http_spdy_module. Этот модуль не создается по умолчанию, его следует включить с помощью
Модуль ngx_http_xslt_module (0.7.8+) — это фильтр, преобразующий XML-ответы с использованием еще одной таблицы стилей.
Имена серверов определяются с помощью директивы server_name и определяют, какой блок используется для данного запроса.
Чтобы превратить соединение между клиентом и сервером из HTTP/1.1 в WebSocket, используется доступный механизм переключения протоколов.
nginx вначале решает, какой из серверов должен обработать запрос. Рассмотрим простую конфигурацию, где все три виртуальных сервера слушают на порту *:80:
В этой конфигурации, чтобы определить, какому серверу следует направить запрос, nginx проверяет только поле “Host” заголовка запроса. Если его значение не соответствует ни одному из имён серверов или в заголовке запроса нет этого поля вовсе, nginx направит запрос в сервер по умолчанию для этого порта. В вышеприведённой конфигурации сервером по умолчанию будет первый сервер, что соответствует стандартному поведению nginx по умолчанию. Сервер по умолчанию можно задать явно с помощью параметра default_server в директиве listen:
Параметр default_server появился в версии 0.8.21. В более ранних версиях вместо него следует использовать параметр default .
Следует иметь в виду, что сервер по умолчанию является свойством слушающего порта, а не имени сервера. Подробнее это обсуждается ниже.
Как предотвратить обработку запросов без имени сервера
Если запросы без поля “Host” в заголовке не должны обрабатываться, можно определить сервер, который будет их отклонять:
Здесь в качестве имени сервера указана пустая строка, которая соответствует запросам без поля “Host” в заголовке, и возвращается специальный для nginx код 444, который закрывает соединение.
Начиная с версии 0.8.48 настройка server_name «» является стандартной и может явно не указываться. В более ранних версиях в качестве стандартного имени сервера выступало имя машины (hostname).
Определение виртуального сервера по имени и IP-адресу
Рассмотрим более сложную конфигурацию, в которой некоторые виртуальные серверы слушают на разных адресах:
В этой конфигурации 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 не указан в списке имён серверов.
Как уже говорилось, сервер по умолчанию является свойством слушающего порта, поэтому у разных портов могут быть определены свои серверы по умолчанию:
Конфигурация простого сайта 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 |