Шаблонная подпапка в блоке location nginx

Вопрос или проблема

У меня есть следующая конфигурация рабочего виртуального хоста:

server {
listen       443 ssl http2;
server_name  example.com;
root  /home/sites/example.com/html; #основной каталог для основного домена сайта
index index.php index.html index.htm;

location / {
            try_files $uri $uri/ /index.php?$args;
        }
...

}

Затем я хочу создать подсайт с этой структурой example.com/sub1, но для удобства организации я не хочу, чтобы sub1 находился в /home/sites/example.com/html. Я предпочел бы, чтобы он находился в /home/sites/example.com/subsites. Поэтому я добавляю этот блок location, и он работает.

location /sub1/ {
  root  /home/sites/example.com/subsites;
  ....
}

Проблема в том, что если я хочу создать еще один подсайт, мне нужно скопировать этот блок и немного изменить его. Например, для sub2 мне нужно создать каталог с именем sub2 в /home/sites/example.com/subsites и затем добавить блок location, как этот:

location /sub2/ {
   root  /home/sites/example.com/subsites;
    ....
}

и я могу получить к нему доступ через example.com/sub2.

Я хочу сделать блок location с использованием регулярных выражений, чтобы каждый раз, когда я создаю каталог в /home/sites/example.com/subsites (dir3, dir4, dir5,… dirN), эти вновь созданные каталоги были доступны через example.com/dir3, example.com/dir4, example.com/dir5,…example.com/dirN. Я пробовал с этим блоком, nginx перезагрузился нормально, но я не могу получить доступ к вновь созданным каталогам и получаю только ошибку 404.

location ~* "/dir([0-9]{1,4})/" {
root  /home/sites/example.com/subsites;
}

Это странная проблема, я думаю. В моем .conf файле есть такие блоки:

location ~* /\.well-known {
    allow all;
}

location ~* /\. {
    deny all;
}

location ~* /(?:uploads|files)/.*\.php$ {
    deny all;
}

location ~* \.(jpg|jpeg|gif|png|css|js|swf|ico|pdf|svg|eot|ttf|woff)$ {
    expires 60d;
    access_log off;
}

Когда я ставлю этот блок после этих блоков и пытаюсь получить доступ к example.com/dir3 (после создания каталога dir3 в /home/sites/example.com/subsites), он показывает страницу 404.

location ~* "/dir([0-9]{1,4})/" {
root  /home/sites/example.com/subsites;
}

Проблема решается перемещением этого блока выше этих блоков. Я не знаю причины этого, но проблема решена, в любом случае.

Ответ или решение

Для настройки wildcard подкаталогов в Nginx необходимо учитывать особенности работы директив и порядок их обработки. Мы рассмотрим ваш сценарий, используя предоставленные вами данные, а также объясним, почему перемещение блока с регулярным выражением решило вашу проблему.

Проблема и решение

Вы хотите сделать так, чтобы каждый новый подкаталог (например, dir3, dir4 и т.д.) в директории /home/sites/example.com/subsites был доступен по адресу example.com/dir3, example.com/dir4 и так далее. Начальная попытка была выполнена с использованием следующего блока:

location ~* "/dir([0-9]{1,4})/" {
    root  /home/sites/example.com/subsites;
}

Этот блок должен был соответствовать URL с подкаталогом dir и цифрами. Однако при добавлении этого блока в конфигурацию Nginx ниже других блоков вы столкнулись с ошибкой 404, что указывает на отсутствие соответствия или неправильную настройку.

Почему это произошло?

В Nginx порядок обработки блоков location имеет критическое значение. Когда Nginx получает запрос, он проходит по всем определённым блокам и выбирает первый, который соответствует условиям. Если ваш блок с регулярным выражением находится после более общих определений и специфичных правил (например, для .well-known, доступа и обработки файлов), то Nginx мог выбирать эти блоки раньше, тем самым блокируя доступ к вашим подкаталогам.

Оптимальная конфигурация

Для вашего случая правильная структура должна выглядеть примерно так:

server {
    listen       443 ssl http2;
    server_name  example.com;
    root  /home/sites/example.com/html;
    index index.php index.html index.htm;

    # Общий блок для всех подкаталогов
    location ~* ^/dir([0-9]{1,4})/ {
        alias /home/sites/example.com/subsites;
        try_files $uri $uri/ =404;
    }

    # Ваши другие блоки
    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~* /\.well-known {
        allow all;
    }

    location ~* /\. {
        deny all;
    }

    location ~* /(?:uploads|files)/.*\.php$ {
        deny all;
    }

    location ~* \.(jpg|jpeg|gif|png|css|js|swf|ico|pdf|svg|eot|ttf|woff)$ {
        expires 60d;
        access_log off;
    }
}

Объяснение изменений

  1. Порядок блоков: Перемещение блока с регулярным выражением выше других блоков позволяет Nginx своевременно обрабатывать запросы на доступ к подкаталогам dirN. Это предотвращает ситуацию, когда более специфичные блоки отказывают в доступе, прежде чем запрос достигнет вашего блока.

  2. Использование alias: В отличие от root, директива alias позволяет корректно перезаписывать путь запроса на фактический путь к папке на сервере, что важно при работе с подкаталогами.

  3. try_files: Эта директива проверяет существование запрашиваемых файлов и предоставляет более детализированный контроль над тем, что происходит, когда ресурс не найден. Если файл не существует, Nginx возвращает 404.

Заключение

Теперь, с правильно настроенным блоком и его местоположением в конфигурации, вы сможете добавлять новые подкаталоги в /home/sites/example.com/subsites без необходимости изменять конфигурацию сервера. Каждый новый подкаталог автоматически станет доступным по соответствующему URL. Эта конфигурация сделает вашу структуру обслуживающей подкаталоги более гибкой и масштабируемой.

Оцените материал
Добавить комментарий

Капча загружается...