Probleme mit mehreren Nginx-Standorten

14

Ich versuche derzeit, 3 Anwendungen aus einem Repository in 3 zu unterteilen, behalte jedoch die URL-Struktur bei, sodass grundsätzlich verschiedene Speicherorte unter derselben Domain von verschiedenen Anwendungen bereitgestellt werden müssen.

Ich habe Probleme damit, dass eine der Apps der Fallback für nicht vorhandene URLs sein muss. Wenn die erste nicht übereinstimmt und die zweite nicht, sollte die dritte die Anfrage bearbeiten

Die Struktur, die ich habe, ist:

/ etc / nginx / sites-enabled / main_site, hier, abgesehen von Servername und Protokollen, habe include /etc/nginx/subsites-enabled/*ich 3 Konfigurationsdateien, eine für jede der Apps.

Jede der 3 Konfigurationsdateien enthält einen Standortblock.

Ich habe einen negativen Lookahead in Regex versucht (im Grunde genommen habe ich versucht, die URLs, mit denen die anderen Apps umgehen, fest zu codieren), bin aber gescheitert.

Also, um zusammenzufassen:

/ und / community sollten von /etc/nginx/subsites-enabled/example.org/home geliefert werden (ein paar Perl-Skripte)

/ news sollte von /etc/nginx/subsites-enabled/example.org/news (wordpress) geliefert werden

alles andere sollte von /etc/nginx/subsites-enabled/example.org/app (Kuchen-App) geliefert werden

Das Perl-Bit funktioniert gut. Das Problem, das ich habe, ist, dass die App Nachrichten übernimmt (wahrscheinlich, weil sie passt. *), Ich habe verschiedene Optionen ausprobiert (ich bin seit 2 Tagen dabei), aber keine von ihnen hat alle Probleme gelöst (manchmal) statische Assets würden nicht funktionieren, etc).

Meine Konfiguration ist:

/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;
}

/ etc / ngins / subsites-enabled / news

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;
  }
}

/ etc / nginx / subsites-enabled / app:

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;
  }
}
Andrei Serdeliuc
quelle
a) Veröffentlichen Sie Ihre Konfiguration zusammen mit einigen Beispielen, wo verschiedene Weiterleitungen (einschließlich der für nicht vorhandene URLs) gespeichert werden sollen. b) Verwenden Sie try_files mit einem benannten Standortblock (mit dem @Präfix), der Ihrer Standard-App zugeordnet ist. Sie können auch eine error_page einrichten, die einen 404 einem benannten Ort zuordnet.
cyberx86
@ cyberx86 Ich habe weitere Details und meine Konfiguration hinzugefügt
Andrei Serdeliuc
Ein kurzer Blick deutet auf ein paar Dinge hin: a) Der Regex-Abgleich hat Vorrang vor herkömmlichen Zeichenfolgen - also stimmt Ihr App-Block mit Ihrem News-Block überein - versuchen Sie es location ^~ /news. b) Für Ihren App-Block sollten Sie in der Lage sein, dies zu tun location /(dies ist nicht dasselbe wie location = /, sollte aber mit allem übereinstimmen, was noch nicht übereinstimmt. c) In einigen Fällen (insbesondere bei regulären Ausdrücken) spielt die Reihenfolge eine Rolle. Möglicherweise möchten Sie die 3 kombinieren Dateien in eine einzelne Datei mit den Blöcken in der richtigen Reihenfolge. Verwenden Sie stattdessen auch try_files !-e. Siehe schließlich wiki.nginx.org/HttpCoreModule#location .
cyberx86
Ich habe so ziemlich jede Variante ausprobiert, einschließlich der Kombination zu einer einzelnen Datei (obwohl sie separat sein müssen, da sie separat bereitgestellt werden), funktioniert keine davon. Nachrichten werden nur von der App verarbeitet.
Andrei Serdeliuc
Nun, ich denke, ich habe es gelöst - ein bisschen kniffliger als ich ursprünglich erwartet hatte - aber es macht auf jeden Fall Spaß, sich mit Verstand zu messen. Danke für das Rätsel.
cyberx86

Antworten:

45

Es gibt ein paar Probleme mit deiner Konfiguration, die beiden relevanten sind:

  1. Pfade innerhalb eines Standortblocks enthalten weiterhin den übereinstimmenden Pfad.
  2. Umschreiben mit 'last' fährt fort, indem alle verfügbaren Standorte nach einem Match durchsucht werden (sie brechen aus dem aktuellen Standortblock aus).

Nehmen Sie zum Beispiel die URL example.org/news/test.htm

  • Der location /newsBlock passt dazu
  • Der verwendete Pfad ist dann /news/test.htm- dies ändert sich nicht, nur weil es sich im Ortsblock befindet
  • Wenn Sie den Pfad zur document_root hinzufügen, erhalten Sie: /var/www/vhosts/news/news/test.htm
  • Ihre if (!-e $request_filename)Anweisung sollte diese nicht vorhandene Datei erfassen
  • Sie schreiben den Pfad zu /index.php
  • Da Sie lastdie Prozesse verwenden, beginnt es von vorne (Ausbruch aus dem Standortblock)
  • /index.phpwird jetzt von der gefangen genommen location /app block.

Das oben erwähnte Problem mit der root-Direktive wird verschärft, wenn Sie zu Ihrem App-Standortblock wechseln. Anders als beim Block "Nachrichten", bei dem Sie möglicherweise nur "Nachrichten" aus dem Pfad entfernen könnten (da sie wieder hinzugefügt werden), können Sie dies nicht für den App-Pfad tun, der mit "Webroot" endet.

Die Lösung liegt in der aliasRichtlinie. Das ändert das document_root nicht aber es ändert den Dateipfad, der verwandt wird, um die Anforderung zu bedienen. Leider rewriteund try_filesneigen dazu, sich ein bisschen unerwartet zu verhalten alias.

Beginnen wir mit einem einfachen Beispiel - kein PHP - nur HTML und Ihr Perl-Block - aber mit einer Ordnerstruktur, die Ihrer entspricht (getestet auf 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 = / - stimmt nur mit dem Stammpfad überein
  • location ^~ /community - passt zu jedem Pfad, der mit / community beginnt
  • location ~ \.pl - stimmt mit allen Dateien überein, die .pl enthalten
  • location ^~ /news - passt zu jedem Pfad, der mit / news beginnt
  • location ^~ /app - Stimmt mit jedem Pfad überein, der mit / app beginnt
  • location / - stimmt mit allen Pfaden überein, die oben nicht übereinstimmen

Sie sollten in der Lage sein, das ^~- zu entfernen , es kann jedoch eine leichte Leistungsverbesserung bewirken, da die Suche abgebrochen wird, sobald eine Übereinstimmung gefunden wurde.

Obwohl es eine einfache Angelegenheit sein sollte, die PHP-Blöcke wieder hinzuzufügen, gibt es leider eine leichte Schwierigkeit - try_files(und Ihr Umschreiben) führt nicht dazu, dass der gewünschte Pfad zum verschachtelten Standortblock übergeben wird - und verwendet wird, aliaswenn nur die Erweiterung vorhanden ist im Location Block angegeben funktioniert nicht.

Eine Lösung besteht darin, separate Standortblöcke zu verwenden, die zusammen mit der Alias ​​- Direktive eine Erfassung durchführen. Dies ist zwar nicht sehr elegant, funktioniert aber, soweit ich das beurteilen kann (erneut getestet unter Nginx 1.0.12, CentOS 6) Natürlich habe ich CakePHP, Wordpress und Perl nicht eingerichtet - ich habe nur ein paar PHP- und HTML-Dateien in jedem Ordner verwendet.

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;
    }
}

Die obige Konfiguration übernimmt die einfache und nimmt zwei Änderungen vor:

  • Fügen Sie zwei Standortblöcke hinzu:
    • location ~* ^/news/(.*\.php)$ - Stimmt mit allen Dateien überein, die mit .php enden, wobei die Pfade mit / news / beginnen.
    • location ~* ^/app/(.*\.php)$ - Stimmt mit allen Dateien überein, die mit .php enden, wobei die Pfade mit / app / beginnen.
  • Entfernen Sie die ^~Übereinstimmung - dies ist erforderlich, damit die beiden hinzugefügten Standortblöcke mit den Pfaden übereinstimmen können (andernfalls würde die Übereinstimmung in den Blöcken / news oder / app aufhören).

Es sollte beachtet werden, dass die Reihenfolge für den Standortabgleich hier sehr wichtig ist:

  • Genaue Übereinstimmungen zuerst (mit =)
  • Stimmt mit ^~Sekunde überein
  • Passende Regex-Blöcke
  • Konventionelle Zeichenfolgen - nur wenn kein passender regulärer Ausdruck gefunden wird

Ein passender regulärer Ausdruck ersetzt einen geraden String!

Ein wichtiger Punkt ist, dass bei der Verwendung von Captures mit Alias ​​die gesamte URL ersetzt wird - nicht nur der führende Ordner. Leider heißt das, dass $fastcgi_script_nameleer gelassen wird - also habe ich $1oben stattdessen verwendet.

Ich bin sicher, dass Sie einige Änderungen vornehmen müssen, aber die Grundvoraussetzung sollte funktionsfähig sein. Sie sollten in der Lage sein, die Blöcke nach Bedarf in mehrere Dateien aufzuteilen - die Reihenfolge sollte sich nicht auf die Konfiguration auswirken.

cyberx86
quelle
2
Alter, ich wünschte, ich könnte dich 100 Mal unterstützen. Du bist einfach großartig. Vielen Dank!
Andrei Serdeliuc