Nginx problemi di posizione multipla


14

Attualmente sto cercando di dividere 3 applicazioni da un repository in 3, ma mantenendo la struttura dell'URL, quindi sostanzialmente posizioni diverse nello stesso dominio devono essere consegnate da applicazioni diverse.

Quello con cui sto lottando è che una delle app deve essere il fallback per gli URL inesistenti, quindi se la prima non corrisponde e la seconda no, la terza dovrebbe gestire la richiesta

La struttura che ho è:

/ etc / nginx / sites-enabled / main_site, qui, a parte server_name e i log che ho include /etc/nginx/subsites-enabled/*, dove ho 3 file di configurazione, uno per ciascuna delle app.

Ognuno dei 3 file di configurazione contiene un blocco di posizione.

Ho provato lookahead negativo in regex (fondamentalmente cercando di codificare gli URL gestiti dalle altre app) ma non ci sono riuscito.

Quindi, per riassumere:

/ e / community dovrebbero essere forniti da /etc/nginx/subsites-enabled/example.org/home (alcuni script perl)

/ le notizie dovrebbero essere fornite da /etc/nginx/subsites-enabled/example.org/news (wordpress)

tutto il resto dovrebbe essere consegnato da /etc/nginx/subsites-enabled/example.org/app (app per torte)

Il bit perl funziona bene. Il problema che sto riscontrando è che l'app sta rilevando le notizie (probabilmente perché corrisponde. *), Ho provato varie opzioni (ci sono stato per 2 giorni) ma nessuno di loro ha risolto tutti i problemi (a volte le risorse statiche non funzionerebbero, ecc.).

La mia configurazione è:

/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 / siti secondari abilitati / notizie

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 / siti secondari abilitati / 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;
  }
}

a) pubblica la tua configurazione insieme ad alcuni esempi di dove dovrebbero andare i vari reindirizzamenti (compresi quelli per URL inesistenti). b) usa try_files con un blocco di posizione denominato (usando il @prefisso) che si associa alla tua app predefinita. Puoi anche impostare una pagina_errore che associa un 404 a una posizione denominata.
cyberx86,

@ cyberx86 Ho aggiunto ulteriori dettagli e la mia configurazione
Andrei Serdeliuc,

Una rapida occhiata suggerisce alcune cose: a) la corrispondenza regex ha la precedenza sulle stringhe convenzionali - quindi il blocco dell'app corrisponderà al blocco delle notizie - prova location ^~ /news. b) per il tuo blocco app, dovresti essere in grado di fare location /(questo non è lo stesso di location = /, ma dovrebbe corrispondere a tutto ciò che non è già abbinato. c) in alcuni casi (in particolare regex), l'ordine è importante - potresti voler combinare il 3 file in un singolo file con i blocchi nell'ordine giusto. Inoltre, utilizzare try_files anziché !-e. Infine, vedi wiki.nginx.org/HttpCoreModule#location .
cyberx86,

Ho provato praticamente ogni variante di quelle, inclusa la loro combinazione in un singolo file (anche se devono essere separate poiché vengono distribuite separatamente), nessuna di esse funziona. Le notizie vengono gestite dall'app.
Andrei Serdeliuc,

Beh, penso di averlo risolto - un po 'più complicato di quanto mi aspettassi inizialmente - ma sicuramente divertente da abbinare allo spirito. Grazie per il puzzle.
cyberx86,

Risposte:


45

Ci sono alcune cose che non vanno nella tua configurazione, le due rilevanti sono:

  1. I percorsi all'interno di un blocco posizione includono comunque il percorso corrispondente.
  2. Le riscritture con "last" continuano esaminando tutte le posizioni disponibili per una corrispondenza (escono dal blocco posizione corrente).

Ad esempio, prendi l'URL example.org/news/test.htm

  • Il location /newsblocco lo abbinerà
  • Il percorso utilizzato è quindi /news/test.htm: questo non cambia, solo perché si trova nel blocco posizione
  • Aggiungendo il percorso a document_root, ottieni: /var/www/vhosts/news/news/test.htm
  • La tua if (!-e $request_filename)dichiarazione dovrebbe acquisire questo file inesistente
  • Riscrivi il percorso a /index.php
  • Dal momento che stai usando lasti processi ricomincia da capo (rompendo il blocco posizione)
  • /index.phpviene ora catturato dal location /app block.

Il problema sopra menzionato, con la direttiva root, è aggravato quando vai al blocco della posizione dell'app. A differenza del blocco "news", in cui è possibile rimuovere semplicemente "news" dal percorso (poiché verrà aggiunto di nuovo), non è possibile farlo per il percorso dell'app, che termina in "webroot".

La soluzione sta nella aliasdirettiva. Ciò non modifica root_documento, ma cambia il percorso del file utilizzato per servire la richiesta. Sfortunatamente, rewritee try_filestendo a comportarmi un po 'inaspettatamente con alias.

Cominciamo con un semplice esempio - niente PHP - solo HTML e il tuo blocco Perl - ma con una struttura di cartelle corrispondente alla tua (testata su 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 = / - corrisponderà solo al percorso principale
  • location ^~ /community - corrisponderà a tutti i percorsi che iniziano con / community
  • location ~ \.pl - corrisponderà a tutti i file che contengono .pl
  • location ^~ /news - corrisponderà a tutti i percorsi che iniziano con / news
  • location ^~ /app - corrisponderà a tutti i percorsi che iniziano con / app
  • location / - corrisponderà a tutti i percorsi non corrispondenti sopra

Dovresti essere in grado di rimuovere il ^~- ma potrebbe offrire un leggero miglioramento delle prestazioni, poiché interrompe la ricerca una volta trovata una corrispondenza.

Mentre dovrebbe essere semplice aggiungere nuovamente i blocchi PHP, c'è, purtroppo, una leggera difficoltà - try_files(e la tua riscrittura) non finiscono per passare il percorso desiderato al blocco posizione nidificato - e usare aliasquando solo l'estensione è specificato nel blocco posizione non funziona.

Una soluzione consiste nell'utilizzare blocchi di posizione separati che eseguono un'acquisizione insieme alla direttiva alias: non è abbastanza elegante, ma per quanto ne so, funziona (di nuovo, testato su Nginx 1.0.12, CentOS 6 - di ovviamente, non ho installato CakePHP, Wordpress e Perl - ho solo usato un paio di file PHP e HTML in ogni cartella)

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

La configurazione sopra, prende quella sopra e apporta due modifiche:

  • Aggiungi due blocchi posizione:
    • location ~* ^/news/(.*\.php)$ - corrisponderà a tutti i file che terminano in .php, con percorsi che iniziano con / news /
    • location ~* ^/app/(.*\.php)$ - corrisponderà a tutti i file che terminano in .php, con percorsi che iniziano con / app /
  • Rimuovi la ^~corrispondenza: è necessario affinché i due blocchi di posizione aggiunti possano corrispondere ai percorsi (altrimenti la corrispondenza si interrompe sui blocchi / news o / app).

Va notato che l'ordine per la corrispondenza della posizione è molto importante qui:

  • Prima le partite esatte (usando =)
  • Corrisponde al ^~secondo
  • Blocchi regex corrispondenti
  • Stringhe convenzionali - solo se non viene trovata alcuna regex corrispondente

Una regex corrispondente sostituirà una stringa dritta!

Un punto importante da ricordare è che quando le acquisizioni vengono utilizzate con l'alias, l'intero URL viene sostituito, non solo la cartella principale. Sfortunatamente, questo significa che $fastcgi_script_nameviene lasciato vuoto, quindi ho usato $1sopra invece.

Sono sicuro che dovrai apportare alcune modifiche, ma la premessa di base dovrebbe essere funzionale. Dovresti essere in grado di separare i blocchi in più file secondo necessità - l'ordinamento non dovrebbe influenzare la configurazione.


2
Amico, vorrei poterti votare 100 volte. Sei semplicemente fantastico. Grazie!
Andrei Serdeliuc,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.