Nginx несколько проблем с расположением

14

В настоящее время я пытаюсь разделить 3 приложения из одного репозитория на 3, но сохраняю структуру URL, поэтому разные приложения в основном должны доставлять разные местоположения в одном домене.

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

У меня есть структура:

/ etc / nginx / sites-enabled / main_site, здесь, кроме имени сервера и журналов include /etc/nginx/subsites-enabled/*, где у меня есть 3 файла конфигурации, по одному для каждого приложения.

Каждый из 3 файлов конфигурации содержит блок местоположения.

Я попытался использовать regex с отрицательным прогнозом (в основном пытался жестко закодировать URL-адреса, которые обрабатывают другие приложения), но не получилось.

Итак, подведем итог:

/ и / сообщество должно быть доставлено с помощью /etc/nginx/subsites-enabled/example.org/home (несколько сценариев на Perl)

/ новости должны быть доставлены /etc/nginx/subsites-enabled/example.org/news (wordpress)

все остальное должно быть доставлено с помощью /etc/nginx/subsites-enabled/example.org/app (приложение для торта)

Бит perl работает отлично. У меня проблема в том, что приложение получает новости (возможно, потому что они совпадают. *), Я пробовал различные варианты (я занимался этим 2 дня), но ни одна из них не решила все проблемы (иногда статические активы не будут работать и т. д.).

Моя конфигурация:

/etc/nginx/sites-enabled/example.org:

server {
    listen   80;
    server_name example.org;
    error_log /var/log/nginx/example.org.log;

    include /etc/nginx/subsites-enabled/example.org/*;
}

/etc/nginx/subsites-enabled/example.org/home:

location = / {
  rewrite ^.*$ /index.pl last;
}

location ~* /community(.*) {
  rewrite ^.*$ /index.pl last;
}

location ~ \.pl {
  root   /var/www/vhosts/home;
  access_log /var/log/nginx/home/access.log;
  error_log /var/log/nginx/home/error.log;

  include /etc/nginx/fastcgi_params;
  fastcgi_index index.pl;
  fastcgi_param SCRIPT_FILENAME /var/www/vhosts/home$fastcgi_script_name;
  fastcgi_pass  unix:/var/run/fcgiwrap.socket;
}

/ И т.д. / ngins / подсайты с поддержкой / Новости

location /news {
  access_log /var/log/nginx/news/access.log;
  error_log /var/log/nginx/news/error.log debug;

  error_page 404 = /news/index.php;

  root /var/www/vhosts/news;

  index index.php;

  if (!-e $request_filename) {
      rewrite ^.*$ /index.php last;
  }

  location ~ \.php {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/vhosts/news$fastcgi_script_name;
  }
}

/ И т.д. / Nginx / подсайты с поддержкой / приложение:

location ~ .* {
  access_log /var/log/nginx/app/access.log;
  error_log /var/log/nginx/app/error.log;

  rewrite_log on;

  index index.php;
  root /var/www/vhosts/app/app/webroot;

  if (-f $request_filename) {
    expires 30d;
    break;
  }

  if (!-e $request_filename) {
    rewrite ^.*$ /index.php last;
  }

  location ~ \.php {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/vhosts/app/app/webroot$fastcgi_script_name;
  }
}
Андрей Серделюк
источник
a) опубликуйте свой конфиг вместе с некоторыми примерами того, куда должны идти различные перенаправления (в том числе для несуществующих URL-адресов). б) использовать try_files с именованным блоком местоположения (используя @префикс), который отображается в ваше приложение по умолчанию. Вы также можете настроить страницу error_, которая отображает 404 на указанное местоположение.
cyberx86
@ cyberx86 Я добавил больше деталей и мой
конфиг
Беглый взгляд подсказывает несколько вещей: а) соответствие регулярному выражению имеет приоритет над обычными строками - так что ваш блок приложения будет совпадать вместо вашего блока новостей - попробуйте location ^~ /news. б) для вашего блока приложения вы должны быть в состоянии сделать location /это (это не то же самое location = /, но должно соответствовать всему, что еще не сопоставлено. в) в некоторых случаях (особенно регулярные выражения) порядок имеет значение - вы можете захотеть объединить 3 файлы в один файл с блоками в правильном порядке. Также используйте try_files вместо !-e. Наконец, смотрите wiki.nginx.org/HttpCoreModule#location .
cyberx86
Я попробовал почти все их варианты, включая объединение их в один файл (хотя они должны быть разделены, так как они развернуты отдельно), но ни один из них не работает. Новости просто обрабатываются приложением.
Андрей Серделюк
Ну, я думаю, что решил это - немного хитрее, чем я первоначально ожидал - но, безусловно, приятно противостоять остроумию. Спасибо за загадку.
cyberx86

Ответы:

45

Есть несколько вещей, которые не так с вашей конфигурации, две соответствующие:

  1. Пути в блоке местоположения все еще включают совпавший путь.
  2. Перезаписи с «последним» продолжаются путем просмотра всех доступных местоположений на совпадение (они выходят из текущего блока местоположений).

Например, возьмите URL example.org/news/test.htm

  • location /newsБлок будет соответствовать его
  • Тогда используется следующий путь /news/test.htm- он не меняется, только потому, что он находится в блоке местоположения
  • Добавив путь к document_root, вы получите: /var/www/vhosts/news/news/test.htm
  • Ваше if (!-e $request_filename)заявление должно захватить этот несуществующий файл
  • Вы переписываете путь к /index.php
  • Поскольку вы используете lastпроцессы начинается снова (выход из блока местоположения)
  • /index.phpсейчас захвачен location /app block.

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

Решение лежит в aliasдирективе. Это не меняет document_root, но меняет путь к файлу, который используется для обслуживания запроса. К сожалению, rewriteи try_filesсклонны вести себя немного неожиданно alias.

Давайте начнем с простого примера - без PHP - только HTML и вашего блока Perl - но со структурой папок, соответствующей вашей (проверено на Nginx 1.0.12, CentOS 6):

server {
    server_name example.org;
    error_log /var/log/nginx/example.org.error.log notice;
    access_log /var/log/nginx/example.org.access.log;
    rewrite_log on;

    location = / {
        rewrite ^ /index.pl last;
    }

    location ^~ /community {
        rewrite ^ /index.pl last;
    }

    location ~ \.pl {
        root   /var/www/vhosts/home;

        [fastcgi_stuff...]
    }


    location ^~ /news {
        alias /var/www/vhosts/news;
        index index.htm;

        try_files $uri $uri/ /news/index.htm;
    }

    location ^~ /app {
        alias /var/www/vhosts/app/app/webroot;
        index index.htm;

        try_files $uri $uri/ /app/index.htm;
    }

    location / {
        rewrite ^/(.*) /app/$1 last;
    }
}
  • location = / - будет соответствовать только корневому пути
  • location ^~ /community - будет соответствовать каждому пути, начиная с / сообщества
  • location ~ \.pl - будет соответствовать всем файлам, которые содержат .pl
  • location ^~ /news - будет соответствовать каждому пути, начиная с / новости
  • location ^~ /app - будет соответствовать каждому пути, начинающемуся с / app
  • location / - будет соответствовать всем путям, не сопоставленным выше

Вы должны быть в состоянии удалить ^~- но это может предложить небольшое улучшение производительности, так как он прекращает поиск, как только найдено совпадение.

Несмотря на то, что добавление блоков PHP должно быть простым делом, к сожалению, есть небольшая сложность - try_files(и ваше переписывание) не в конечном итоге передать желаемый путь к вложенному блоку местоположения - и использовать, aliasкогда только расширение является указанный в блоке местоположения не работает.

Одним из решений является использование отдельных блоков местоположения, которые выполняют захват вместе с директивой псевдонима - это не совсем элегантно, но, насколько я могу судить, оно работает (опять же, протестировано на Nginx 1.0.12, CentOS 6 - из Конечно, я не настраивал CakePHP, Wordpress и Perl - я просто использовал пару файлов PHP и HTML в каждой папке)

server {
    server_name example.org;
    error_log /var/log/nginx/example.org.error.log notice;
    access_log /var/log/nginx/example.org.access.log;
    rewrite_log on;

    location = / {
        rewrite ^ /index.pl last;
    }

    location ^~ /community {
        rewrite ^ /index.pl last;
    }

    location ~ \.pl {
        root   /var/www/vhosts/home;
        access_log /var/log/nginx/home.access.log;
        error_log /var/log/nginx/home.error.log;
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.pl;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_pass  unix:/var/run/fcgiwrap.socket;
    }

    location /news {
        access_log /var/log/nginx/news.access.log;
        error_log /var/log/nginx/news.error.log notice;
        alias /var/www/vhosts/news;
        index index.php;
        try_files $uri $uri/ /news/index.php;
    }

    location ~* ^/news/(.*\.php)$ {
        access_log /var/log/nginx/news.php.access.log;
        error_log /var/log/nginx/news.php.error.log notice;
        alias /var/www/vhosts/news/$1;
        try_files "" /news/index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_NAME $1;
        fastcgi_param SCRIPT_FILENAME /var/www/vhosts/news/$1;
        fastcgi_pass  127.0.0.1:9000;
    }

    location /app {
        alias /var/www/vhosts/app/app/webroot;
        access_log /var/log/nginx/app.access.log;
        error_log /var/log/nginx/app.error.log notice;
        index index.php;
        try_files $uri $uri/ /app/index.php;
    }

    location ~* ^/app/(.*\.php)$ {
        access_log /var/log/nginx/news.access.log;
        error_log /var/log/nginx/news.error.log notice;
        alias /var/www/vhosts/app/app/webroot/$1;
        try_files "" /app/index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_NAME $1;
        fastcgi_param SCRIPT_FILENAME /var/www/vhosts/app/app/webroot/$1;
        fastcgi_pass  127.0.0.1:9000;
    }

    location / {
        rewrite ^/(.*) /app/$1 last;
    }
}

Приведенный выше конфиг, берет простой выше и делает два изменения:

  • Добавьте два блока местоположения:
    • location ~* ^/news/(.*\.php)$ - будет соответствовать всем файлам, заканчивающимся на .php, с путями, начинающимися с / news /
    • location ~* ^/app/(.*\.php)$ - будет соответствовать всем файлам, заканчивающимся на .php, с путями, начинающимися с / app /
  • Удалите ^~сопоставление - это необходимо для того, чтобы два добавленных блока местоположения могли сопоставляться с путями (в противном случае сопоставление остановится на блоках / news или / app).

Следует отметить, что порядок сопоставления местоположений здесь очень важен:

  • Сначала точные совпадения (используя =)
  • Матчи со ^~вторым
  • Соответствующие блоки регулярных выражений
  • Обычные строки - только если не найдено подходящего регулярного выражения

Соответствующее регулярное выражение заменит прямую строку!

Важным моментом является то, что при использовании перехватов с псевдонимом заменяется весь URL-адрес, а не только ведущая папка. К сожалению, это означает, что $fastcgi_script_nameоставлено пустым, поэтому я использовал $1выше.

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

cyberx86
источник
2
Чувак, я бы хотел 100 раз отозвать тебя. Ты просто потрясающий. Благодарность!
Андрей Серделюк