Spec-Zone.ru › nginx

Как 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 "" можно опустить. В более ранних версиях в качестве имени сервера по умолчанию использовалось имя машины.

Смешанные основанные на имени и 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 выбирает местоположение для обработки запроса для типичного простого сайта 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 равна значению директивы 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.
написано Игорем Сысоевым
отредактировано Брайаном Мерсером

© 2002-2021 Igor Sysoev
© 2011-2024 Nginx, Inc.
Licensed under the BSD License.
https://nginx.org/en/docs/http/request_processing.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API