Come servire tutti i file statici esistenti direttamente con NGINX, ma inoltrare il resto a un server backend.


88
location / {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

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

    if (!-f $request_filename) {
        proxy_pass http://127.0.0.1:8080; # backend server listening
        break;
        }
    }

Sopra servirà tutti i file esistenti utilizzando direttamente Nginx (es. Nginx visualizza solo il codice sorgente PHP), altrimenti inoltrerà una richiesta ad Apache. Devo escludere i file * .php dalla regola in modo che anche le richieste per * .php vengano passate ad Apache ed elaborate.

Voglio che Nginx gestisca tutti i file statici e Apache per elaborare tutte le cose dinamiche.

EDIT: esiste un approccio alla lista bianca, ma non è molto elegante, vedi tutte quelle estensioni, non lo voglio.

location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
    access_log off;
    expires 30d;
    }
location / {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
    }

EDIT 2: sulle versioni più recenti di Nginx usa try_filesinvece http://wiki.nginx.org/HttpCoreModule#try_files


Giusto per chiarire le cose: il codice precedente servirà un file statico se esiste sul disco, se il file non esiste la richiesta viene passata ad Apache. Questo funziona la maggior parte del tempo poiché tutti gli URL nelle mie applicazioni usano mod_rewrite (o routing) e non esistono realmente sul disco. Solo l'accesso diretto al nome del file * .php è un'eccezione e deve essere analizzato da Apache.
fmalina

Risposte:


153

Usa try_files e il blocco di posizione con nome ('@apachesite'). Questo rimuoverà la corrispondenza regex non necessaria e if block. Più efficiente.

location / {
    root /path/to/root/of/static/files;
    try_files $uri $uri/ @apachesite;

    expires max;
    access_log off;
}

location @apachesite {
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}

Aggiornamento: il presupposto di questa configurazione è che non esiste alcuno script php in /path/to/root/of/static/files. Questo è comune nella maggior parte dei moderni framework php. Nel caso in cui i tuoi progetti php legacy abbiano sia script php che file statici mescolati nella stessa cartella, potresti dover inserire nella whitelist tutti i tipi di file che vuoi che nginx serva.


sto usando wordpress, quindi dovrei aver bisogno di mettere la cartella di caricamento sul server nginx?
Chameron

7
Il mio problema con questa soluzione: nginx non utilizza l'altra posizione (il proxy) e cerca di mostrare l'elenco delle directory. Quindi lancia un 403 perché l'elenco delle directory non è attivato. Modifica: ok se rimuovi $uri/, funziona.
ChristophLSA

1
Questo proverrebbe / example ad apache ma consentirebbe il download di /example.php.
Terence Johnson,

1
@TerenceJohnson Non è sicuro mettere i file php nella cartella dei file statici. Nota che ho impostato root /path/to/root/of/*static*/files;. php dovrebbero essere messi in una cartella diversa, non direttamente accessibile da Internet.
Chuan Ma,

2
So che è così che dovrebbero essere le cose, ma se qualcuno sta mettendo Nginx davanti a una delle tante comuni applicazioni PHP standard che hanno tutto sotto la radice web e si basano su file .htaccess, non dovrebbero copiare e incolla la tua configurazione.
Terence Johnson,

18

Prova questo:

location / {
    root /path/to/root;
    expires 30d;
    access_log off;
}

location ~* ^.*\.php$ {
    if (!-f $request_filename) {
        return 404;
    }
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}

Si spera che funzioni. Le espressioni regolari hanno una priorità più alta rispetto alle stringhe semplici, quindi tutte le richieste che terminano con .phpdovrebbero essere inoltrate ad Apache se .phpesiste solo un file corrispondente . Il resto verrà gestito come file statici. L'attuale algoritmo di valutazione della posizione è qui .


6

Se usi mod_rewrite per nascondere l'estensione dei tuoi script, o se ti piacciono gli URL carini che terminano con /, allora potresti volerlo avvicinare dall'altra direzione. Di 'a nginx di lasciare che qualsiasi cosa con un'estensione non statica passi ad apache. Per esempio:

location ~* ^.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$
{
    root   /path/to/static-content;
}

location ~* ^!.+\.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|pdf|txt|tar|wav|bmp|rtf|js|flv|swf|html|htm)$ {
    if (!-f $request_filename) {
        return 404;
    }
    proxy_set_header X-Real-IP  $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
}

Ho trovato la prima parte di questo snippet su: http://code.google.com/p/scalr/wiki/NginxStatic


Ha funzionato alla grande, anche se ricevo ancora errori per i file minimizzati (ad esempio site.min.css e main.min.js ecc.). Come li catturerei in una regex di posizione? @lo_fye
Garth,
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.