Nginx если файл не существует

Обновлено: 04.07.2024

Nginx – компактный и производительный веб-сервер, созданный для систем с высоким трафиком. Одной из его сильных сторон является эффективное представление статического контента, например, HTML или медиафайлов. В Nginx используется асинхронная модель с управлением событиями, что обеспечивает предсказуемую производительность при высокой нагрузке.
Динамический контент Nginx передает CGI, FastCGI или другим веб-серверам, например, Apache. Затем этот контент возвращается Nginx для отправки клиенту. В данном руководстве мы рассмотрим базовые принципы и параметры конфигурации Nginx.

Директивы, блоки и контексты

В рассмотренном примере заданы следующие директивы:

Серверные блоки

Независимо от источника установки файлы конфигурации будут содержать серверный блок (или блоки) для веб-сайта, обозначенный словом server. Например:

Директива server_name позволяет размещать несколько доменов на одном IP-адресе (виртуальные хосты). Выбор домена осуществляется на основании информации в заголовке полученного запроса.

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

3.Обработка запросов ко всем доменным именам, начинающимся с example.:

Это полезно, если ваш сервер работает в локальной сети или вы точно знаете все клиенты, которые будут осуществлять запросы, например, front-end прокси-серверы, у которых записи в /etc/hosts настроены на IP-адрес Nginx.

Блоки Location

Nginx всегда выполняет запрос, находя наиболее точное соответствие:

Когда после директивы location указана тильда (

), Nginx определяет соответствие по регулярному выражению. Этот поиск всегда чувствителен к регистру. Таким образом, страница IndexPage.php будет соответствовать первому из приведенных выше примеров, а indexpage.php – нет. Во втором примере регулярному выражению будут соответствовать запросы к /BlogPlanet/ и /BlogPlanet/index.php, но не /BlogPlanet, /blogplanet/, или /blogplanet/index.php. В Nginx используются Perl-совместимые регулярные выражения.
Если вы хотите, чтобы поиск не был чувствителен к регистру, после тильды нужно указать звездочку (

Если указать перед тильдой символ «крышки» (^

), при соответствии запроса указанной строке сервер прекратит поиск более точных соответствий (даже если они есть) и будет использовать эти директивы. Во всем остальном они аналогичны рассмотренным выше директивам.

Директивы обрабатываются в следующем порядке:

  1. Сначала обрабатываются точные соответствия строк. Если соответствие найдено, Nginx прекращает поиск и отвечает на запрос.
  2. Обрабатываются оставшиеся директивы с точно заданными строками. Если Nginx находит соответствие директиве с аргументом ^

Убедитесь, что каждый файл или папка в домене соответствуют условиям хотя бы одной директивы location.

Внутри блока location указываются собственные директивы, например:

В данном примере корень документов находится в директории html/. При установке Nginx в месторасположение по умолчанию она находится в /etc/nginx/html/ . В директиве root также можно использовать абсолютный путь.

Переменная index сообщает Nginx, какой файл передавать, если клиент не указал конкретное имя, например:

Разберем ответы на некоторые запросы

Заключение

Мы разобрали базовые принципы и параметры конфигурации веб-сервера Nginx. Этого достаточно, чтобы настроить простой сайт. Для более подробной информации о директивах файлов конфигурации стоит изучить официальную документацию Nginx.

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

  • Open with Desktop
  • View raw
  • Copy raw contents Copy raw contents Loading

Copy raw contents

Copy raw contents

Конфигурация Nginx и подводные камни

Не важно новичок вы или опытный профессионал в настройке nginx, рано или позно вы можете столкнутся с непонятными проблемами при написании конфигов. Это подводные камни конфигурции nginx и от них никуда не уйти. Далее в этой статье мы рассмотрим эти ситуации и способы их обхода.

В интернете полно некорректных, зачастую неправильных, инструкций по настройке сервера nginx. Нельзя им слепо следовать не понимая, что делает та или иная директива. Множество инструкций и примеров конфигураций просто ужасны, написаны на коленки и не читабельны. Эта статья была написана как ответ на такие инструкции, которые направляют новичков по ложному пути, запутывая их окончательно и заставля задавать одни и теже вопросы на форумах и IRC каналах.

Root внутри блока Location

ПЛОХО:

Это работает. Помещать директиву root внутри блока location это нормально и правильно. Что не правильно в данном случае, дак это то, что директива root повторяется в каждом блоке location , следовательно, если ни один из локейшенов не сработает, то у нас директива root вообще не будет задана.

Правильным решение является вынос директивы root из блоков location в начало блока server . Ниже приведен пример как надо делать правильно:

ХОРОШО:

Повторяющиеся директивы Index

ПЛОХО:

ХОРОШО:

Ипсользование условий If - зло.

Есть небольшая статья по применению условного оператора if , описывающая почему использование if крайне не рекомендуется. Статья называется if - это Зло. . Очень рекомендуем прочитать вам эту статью, и посмотреть на примерах почему оператор if это зло.

ПЛОХО:

ХОРОШО:

Проверка что файл cуществует

Использовать if для проверки наличия файла это просто ужасно. В nginx для этого есть специальная директива try_files , которая делает жизнь на много проще.

ПЛОХО:

ХОРОШО:

Использование директивы try_files подразумевает, что вы можете тестировать не одно условие, а последовательность (цепочку) из нескольких условий. Например, в данном примере проверяется существует-ли файл по указанному $uri , если файл не найден, то проверяется существует-ли директория $uri/ , если и ее нет, то проверка идет дальше по цепочке. Если ниодно условие так и не стработало, то по-умолчанию, nginx выполнит последнее условие в цепочке (в данном случае это /index.html ). Вот еще один повод, чтобы избавиться от использования директивы if .

Шаблон Front Controller и CMS движки, которые его используют

Шаблон Front Controller сейчас очень популярен и используется во многих CMS движках и современных фреймворках на PHP. Далее показан простой пример, применимый для CMS Drupal, Joomla и др.:

ВНИМАНИЕ Названия параметров могут отличаться для разных CMS. Например:

Некоторым движкам вообще не нужны параметры и они вытаскивают всю необходимую информацию из строки запроса REQUEST_URI (например WordPress):

Конечно, эти параметры для других CMS и фреймворков могут отличаться, здесь приведен лишь общий пример. В некоторых ситуациях вам понадобится более комплексное решение, пробуйте и экспериментируйте.

Также вы можете вообще убрать проверку на наличие директории $uri/ , если вам эта проверка не нужна.

Перенаправление всех запросов в PHP

Многие примеры конфигурации nginx рекомендуют все запросы оканчивающиеся на .php перенаправлять (проксировать) в интерпретатор PHP. Но это, вообще-то, потенциальная угроза безопасности на множестве конфигураций PHP, которая может привести к выполнению вредоносного кода на сервере.

Проблемная секция обычно выглядит так:

Здесь каждый запрос оканчивающийся на .php перенаправляется в бекэнд на FastCGI. Угроза безопасности здесь в том, что конфигурация PHP по-умолчанию всегда пытается выяснить какой файл вы хотите выполнить, даже если запрос идет на не существующий файл.

Например, вот запрос к файлу /forum/avatar/1232.jpg/file.php которого на самом деле нет на сервере, но зато на сервере есть файл /forum/avatar/1232.jpg . В данном случае по-умолчанию PHP обработает этот файл /forum/avatar/1232.jpg . А теперь представьте, что в этом файле содержится вредоносный код для PHP? Соответсвенно он будет выполнен!

Чтобы это исключить, необходимо:

  • Установить директиву cgi.fix_pathinfo=0 в php.ini. Это заставит интерпретатор PHP остановиться на выполнении первого запроса и при отсутствии запрашиваемого ресурса не идти далее по цепочке.
  • Убедится что nginx отправляет в PHP на обработку только определенные файлы, расчитанные на такую обработку. А не все подряд:
  • запретить обработку интерпретатором PHP всех файлов из директории куда пользователи загружают свои файлы:
  • Использовать директиву try_files чтобы отбросить запросы на не существующие файлы:
  • Использовать вложенные секции location , чтобы исключить проблемные условия:

FastCGI путь в SCRIPT_FILENAME

Во многих руководствах по настройке nginx используются абсолютные пути для указания корневой директории сайта. Это частая практика в PHP блоках конфигурации nginx. Но в подключаемых конфигах для настройки парметров FastCGI include fastcgi_params; этого делать не стоит, для этого есть встроенная переменная $document_root .

ПЛОХО:

ХОРОШО:

Вы спросите, где задается переменная $document_root ? Она задается директивой root , которая должна присутствовать в блоке server . И если в вашем конфиге ее там нет, тогда вы наткнулись на первый подводный камень описанный нами в начале этой статьи: Root внутри блока Location , исправляйте ваш конфиг =)

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

ПЛОХО:

ХОРОШО:

ЕЩЕ ЛУЧШЕ:

Посмотрети, на первый вариант, потом на последний, потом опять на первый и опять на последний. Ну что? Первый реврайт запоминает полный путь без учета начального слеша и затем помещает этот путь вместо плейсхолдера $1 . Однако используя встроенную переменную $request_uri мы спокойно можем избавится от всей этой магии с регулярными выражениями.

BAD:

ХОРОШО:

Проксируем все подряд

ПЛОХО:

FFFUUU. В этом примере мы перенаправляем ВСЕ ПОДРЯД. в PHP. Зачем? Для Apache это простительно, но вам нет. Директива try_files придумана не просто так, она проверяет наличие запрашиваемого ресурса (файла) в определнной последовательности. Это значит, что nginx может проверить первое условие, потом второе и т.д. пока по цепочке не дойдет до конца. И если ничего не сработало, то по-умолчанию выполнится последннее условие в цепочке проверок. А это значит, что интерепретатор PHP будет вызываться не каждый раз, а только тогда, кода это действительно необходимо. Обработка запросов при этом ускорится многократно!

Представьте, что идет несколько однотипных запросов на получение файла картинки размеров 1Мб и в примере выше каждый такой запрос будет перенаправлен в PHP.

Ниже показано как избавиться от этого безобразия:

ХОРОШО:

ТОЖЕ ХОРОШО:

Просто, не правда-ли? Мы видим что, если запрашиваемый URI существует, то он будет отработан nginx. Если нет, то проверяется существует ли вообще такая директория $uri/ . Если нет, то уже тогда, по-умолчанию, запрос будет направлен в /index.php и обработан PHP.

Теперь представьте сколько на вашем сайте статического контента (картинок, css-стилей, js-скриптов и т.д.), сколько лишних запросов вы отсекли от обработки через PHP?

Изменения в конфиге не работают

Браузер кеширует запросы! Ваша конфигурация может быть идельной и без единой ошибки, но вы по-прежнему бъетесь головой об стену и пытаетесь понять почему у вас ничего не работает? Что не так? Ответ на этот вопрос: кеш браузера. Когда вы загружаете что-либо, браузер сохраняет это в своем кеше. Он также сохраняет то, как был обработан скачанный файл. Если вы в конфигурации nginx играетесь с блоками <> , скорее всего вы столкнетесь с проблемами кеширования запросов браузером.

  • [Вариант 1] в Firefox нажмите Ctrl+Shift+Delete, проерьте кешь, нажмите кнопку Очистить. Если у вас другой браузер, то погуглите как очищается кеш в нем.
  • [Варинт 2] Используйте для тестирования curl.

Если действия выше не помогают, и вы запускаете nginx на виртуальной машине, причина может быть в sendfile . Просто закомментируйте директиву или установите ее в значение в off . Эта директива может располагаться где-то в вашем конфиге nginx в файле nginx.conf :

Более подробно на эту тему смотрите в официальной документации по nginx.

В данной инструкции мы рассмотрим, в большей степени, перенаправления запросов на другие страницы с помощью NGINX. Также мы немного разберем проксирование и перенаправление на другие файлы.

Настройка перенаправлений

Настройки необходимо вносить в файлах конфигураций виртуальных доменов. В Linux на основе RPM (CentOS, Red Hat), как правило, они расположены в директории /etc/nginx/conf.d/. В Linux на основе Deb (Ubuntu, Debian) — в директории /etc/nginx/sites-enabled/. Во FreeBSD все в одном файле — /usr/local/etc/nginx/nginx.conf.

Саму настройку на перенаправление в NGINX можно прописать несколькими способами.

* $host — имя хоста из запроса, если отсутствует — имя в поле «Host» заголовка, если тоже отсутствует — имя сервера; $request_uri — первоначальный запрос с аргументами (все, что идет после доменного имени).
** где флаги могут быть следующие:

* где коды могут использоваться любые, но чаще всего — 301, 302, 404.

Есть различные мнения, какой из методов лучше и безопаснее, поэтому каким воспользоваться — решать по ситуации. В данных примерах используются оба варианта.

После внесения изменений, необходимо проверить их корректность:

И для их применения перезапустить веб-сервер:

systemctl restart nginx

service nginx restart

* в первом примере перезапуск выполняется на новых системах Linux. Второй пример — на устаревших или FreeBSD.

Проверяя редиректы в браузере, следует учесть, что настройки могут кэшироваться. Для обновления кэша используйте комбинацию Ctrl + F5. Если и это не помогает, закрывайте вкладку и открывайте новую.

С одного домена на другой

C домена без www на домен с www

С www на без www

Все домены, которые обслуживает nginx:

C index.php на / (корень)

Данная настройка позволит перевести все запросы с /index.php на корневой адрес /:

server .
if ($request_uri

Перенаправление запросов для отсутствующих доменов (перенаправление по умолчанию)

или независимо от протокола:

ssl on;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/cert.key;
>

С IP-адреса на домен

В данном случае мы переводим все запросы по IP-адресу на конкретный домен:

Редирект домена и всех его поддоменов

На другой файл

Это скорее не перенаправление, а алиас или rewrite. Позволяет по запросу одного из файлов, отдать другой:

server .
location = /robots.txt rewrite ^/robots.txt$ /robots2.txt;
>
>

* в данном примере по запросу robots.txt, сервер отдаст содержимое robots2.txt.

Часть url на другой сервер

Редирект со слешем

1. Убрать слеш в конце url

server .
if (!-f $request_filename ) rewrite ^/(.*)/$ /$1 permanent;
>
>

2. Добавить слеш в конце url

server .
if (!-f $request_filename ) rewrite ^(.*[^/])$ $1/ permanent;
>
>

Удаляем расширение

Для перенаправления запроса, где в URL есть полное название файла скрипта (с расширением) используем конфигурацию:

server .
if ($request_uri

* в данном случае все запросы, которые заканчиваются на .php или .html, будут перенаправляться на страницы без данных расширений.

На другую страницу

Нам может понадобиться перенаправлять запросы с одной страницы сайта на другую. Приведем примеры, как это сделать с помощью return и rewrite.

а) с помощью rewrite:

server .
rewrite ^/page1$ /page2 permanent;
>

б) с помощью return:

server .
location = /page1 return 301 /page2;
>
>

Удалить часть URL

Иногда нужно удалять часть url. Это можно сделать следующими способами:

server .
rewrite /deleted-url/(.*) /$1 permanent;
>

server .
if ($request_uri

* в данном примере из url мы удалим deleted-url/.

* в данном примере мы проверяем наличие файла, к которому идет обращение. И если его нет, то происходит замена адреса на такое же имя файла с .php на конце.

Перевод запросов, если файла не существует

Данное действие не является редиректом, но близко по смыслу — NGINX проверяет наличие файла скрипта, к которому идет обращение, и если его нет, переводит запрос на другой файл. Как правило, это используется для того, чтобы перевести все обращения на файл index.php.

server .
location / try_files $uri $uri/ /index.php?$query_string;
>
.
>

* в данном примере мы скажем веб-серверу все запросы обрабатывать с помощью файла index.php в корневой директории.

Проксирование

Хоть это и не совсем редирект, рассмотрим примеры его настройки, так как очень часто нужно не перенаправление, а, как раз, обратное проксирование.

1. На другой сервер

.
location / proxy_pass $scheme://192.168.0.15:8080/;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
>

* в данном случае, принимать запросы от браузера и отвечать на них будет NGINX, а сама обработка будет выполняться на сервере с IP-адресом 192.168.0.15 на порту 8080.

* где 10.10.10.10/page — страница, на которую будут перекинуты запросы; dGVzdDp0ZXN0 — логин:пароль test:test, закодированные в формате base64.

2. Часть url на другой сервер

Выше мы рассмотрели пример перенаправления запроса по части веб-адреса. По схожему сценарию мы можем делать проксирование:

3. На другой сайт

Мы можем сделать так, что при переходе по одному адресу у нас будет открываться совершенно другой сайт:

4. На другой сайт по части URL

Если нам нужно настроить проксирование на другой сайт при обращении к определенной странице сайта, настраиваем NGINX так:

5. Редиректы при проксировании

Немного о 301 и 302

В чем принципиальная разница между ответом с кодом 301 и 302? Для обычного посетителя сайта разницы нет. А вот для поискового робота разница огромная.

301-й редирект говорит о склеивании страниц. Это означает для поисковика то, что старая и новая страницы — это одно и то же. Таким образом, результаты ранжирования необходимо сохранить для новой страницы.

302-о перенаправление просто говорит о том, что нужно перейти по другому адресу. Поисковый робот не сохраняет результат выдачи для новой страницы, индексируя его с нуля.

1.last эквивалентно метке [L] в apache, что означает перезапись.
2.break После завершения сопоставления этого правила сопоставление будет прекращено, и следующие правила не будут сопоставлены.
3.redirect возвращает временное перенаправление 302, в адресе браузера будет отображаться URL-адрес перенаправления.
4.permanent возвращает 301 постоянное перенаправление, в адресе браузера будет отображаться URL-адрес после перенаправления.

Используйте last и break для перезаписи URI, и адресная строка браузера останется неизменной. И между ними есть небольшая разница: инструкция псевдонима должна быть помечена последней; когда используется инструкция proxy_pass, должна использоваться метка разрыва. Метка «Последняя» повторно инициирует запрос тега сервера <. >, на котором правило перезаписи выполняется после завершения выполнения этого правила, а метка прерывания завершит сопоставление после сопоставления с этим правилом.

Например: если мы перенаправляем аналогичный URL / photo / 123456 на /path/to/photo/12/1234/123456.jpg

четыре. Инструкции, связанные с правилами NginxRewrite

1. прервать инструкцию

Использовать среду: сервер, местоположение, если;
Функция этой инструкции - завершить текущий набор правил и больше не обрабатывать инструкцию перезаписи.

2. если инструкция

Среда использования: сервер, местоположение
Эта инструкция используется для проверки выполнения условия, и если условие выполняется, выполняется инструкция в фигурных скобках. Если инструкция не поддерживает вложение, она не поддерживает обработку нескольких условий && и ||.

3. инструкция возврата

Синтаксис: код возврата;
Использовать среду: сервер, местоположение, если;
Эта инструкция используется для завершения выполнения правила и возврата кода состояния клиенту.
Пример. Если доступный URL заканчивается на ".sh" или ".bash", будет возвращен код состояния 403.

4. переписать инструкцию

Синтаксис: флаг замены rewriteregex
Использовать среду: сервер, местоположение, если
Эта инструкция перенаправляет URI в соответствии с выражением или изменяет строку. Инструкции выполняются в соответствии с порядком в файле конфигурации. Обратите внимание, что выражение перезаписи действительно только для относительных путей. Если вы хотите сопоставить имя хоста, вы должны использовать оператор if. Примеры следующие:

5. установка инструкции

Синтаксис: значение setvariable; Значение по умолчанию: нет; Использовать среду: сервер, местоположение, если;
Эта инструкция используется для определения переменной и присвоения ей значения. Значение переменной может быть комбинацией текста, переменной и текстовой переменной.
Пример: set $ varname "hello world";

6. инструкция Uninitialized_variable_warn

Пятерки. Пример написания правила Nginx Rewrite

1. Если файл и каталог, к которым осуществляется доступ, не существуют, перенаправьте на файл php.
2. Обмен каталогов / 123456 / xxxx ====> / xxxx? Если клиент использует браузер IE, выполните перенаправление в каталог / ie.
4. Нет доступа к нескольким каталогам
5. Запретить доступ к файлам, начинающимся с / data.
6. Запрещен доступ к файлам с расширением .sh, .flv, .mp3.
7. Установите время кеширования браузера для определенных типов файлов.
8. Установите срок действия для файлов favicon.ico и robots.txt;

Здесь favicon.ico - 99 дней, robots.txt - 7 дней, а журналы ошибок 404 не записываются.

9. Установите срок действия файла, здесь 600 секунд, и журналы доступа не записываются.
10. Подайте антипиявку и установите срок действия.
11. Разрешить только фиксированный IP-адрес для посещения веб-сайта и добавить пароль
12. Конвертируйте файлы в многоуровневой директории в один, чтобы усилить SEO-эффект.

/job-123-456-789.html указывает на /job/123/456/789.html

13. Перенаправление, когда файлы и каталоги не существуют:
14. Укажите папку в корневом каталоге на каталог второго уровня.

Например, / shanghaijob / указывает на / area / shanghai /
Если вы измените последнее на постоянное, адресная строка браузера будет отображаться как / location / shanghai /

Проблема с приведенным выше примером заключается в том, что он не будет соответствовать при посещении / шанхай

Таким образом можно получить доступ к / shanghai, но нельзя использовать относительные ссылки на странице.
Например, реальный адрес ./list_1.html - /area/shanghia/list_1.html, он станет /list_1.html, что приведет к недоступности.
Затем добавляю, что автоматического перехода недостаточно
(-d $ request_filename) У него есть условие, что это должен быть настоящий каталог, но моя перезапись нет, поэтому это не имеет никакого эффекта

Когда вы узнаете причину, это легко сделать, позвольте мне прыгнуть вручную

15. Перенаправление доменного имени
16. Переадресация мультидоменных имен

шесть. глобальные переменные nginx

Семь. Соответствие правил Apache и Nginx

RewriteCond Apache соответствует Nginx, если
RewriteRule Apache соответствует перезаписи Nginx
Apache [R] соответствует перенаправлению Nginx
[P] Apache соответствует последней версии Nginx
Apache [R, L] соответствует перенаправлению Nginx
[P, L] Apache соответствует последней версии Nginx
[PT, L] Apache соответствует последней версии Nginx

Читайте также: