Cara melayani semua file statis yang ada secara langsung dengan NGINX, tetapi proksi sisanya ke 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;
        }
    }

Di atas akan melayani semua file yang ada secara langsung menggunakan Nginx (misalnya Nginx hanya menampilkan kode sumber PHP), jika tidak, teruskan permintaan ke Apache. Saya perlu mengecualikan file * .php dari aturan sehingga permintaan * .php juga diteruskan ke Apache dan diproses.

Saya ingin Nginx menangani semua file statis dan Apache untuk memproses semua hal dinamis.

EDIT: Ada pendekatan daftar putih, tetapi tidak terlalu elegan, Lihat semua ekstensi itu, saya tidak menginginkan ini.

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: Pada versi yang lebih baru dari penggunaan Nginx try_filesbukan http://wiki.nginx.org/HttpCoreModule#try_files

fmalina.dll
sumber
Hanya untuk membersihkan hal-hal: kode di atas akan melayani file statis jika ada di disk, jika file tidak ada permintaan diteruskan ke Apache. Ini bekerja hampir sepanjang waktu karena semua URL dalam aplikasi saya menggunakan mod_rewrite (atau routing) dan tidak benar-benar ada di disk. Hanya akses langsung ke nama file * .php yang merupakan pengecualian dan perlu diurai oleh Apache.
fmalina

Jawaban:

153

Gunakan try_files dan beri nama blok lokasi ('@apachesite'). Ini akan menghapus kecocokan regex yang tidak perlu dan jika diblokir. Lebih efisien.

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

Pembaruan: Asumsi dari konfigurasi ini adalah bahwa tidak ada skrip php di bawah /path/to/root/of/static/files. Ini umum terjadi di sebagian besar kerangka kerja php modern. Jika proyek php lawas Anda memiliki skrip php dan file statis yang tercampur dalam folder yang sama, Anda mungkin harus memasukkan semua jenis file yang Anda inginkan ke nginx ke daftar putih.

Chuan Ma
sumber
Saya menggunakan wordpress, jadi haruskah saya meletakkan folder upload di server nginx?
Chameron
7
Masalah saya dengan solusi ini: nginx tidak menggunakan lokasi lain (proxy) dan mencoba menampilkan daftar direktori. Jadi ini melempar 403 karena daftar direktori tidak diaktifkan. Edit: Ok jika Anda menghapusnya $uri/maka itu berhasil.
ChristophLSA
1
Ini akan menjadi proxy / example ke apache tetapi mengizinkan /example.php untuk diunduh.
Terence Johnson
1
@TerenceJohnson Tidak aman untuk meletakkan file php Anda di bawah folder file statis. Perhatikan bahwa saya mengatur root /path/to/root/of/*static*/files;. File php harus diletakkan di folder yang berbeda, tidak langsung dapat diakses dari internet.
Chuan Ma
2
Saya tahu begitulah seharusnya, tetapi jika seseorang menempatkan Nginx di depan salah satu dari banyak aplikasi PHP umum yang memiliki segalanya di bawah web root dan bergantung pada file .htaccess, mereka tidak boleh menyalin dan tempel konfigurasi Anda.
Terence Johnson
18

Coba ini:

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

Semoga berhasil. Ekspresi reguler memiliki prioritas lebih tinggi daripada string biasa, jadi semua permintaan yang diakhiri dengan .phpharus diganti ke Apache jika hanya .phpada file yang sesuai . Sisanya akan ditangani sebagai file statis. Algoritme sebenarnya untuk mengevaluasi lokasi ada di sini .

Jasiu
sumber
6

Jika Anda menggunakan mod_rewrite untuk menyembunyikan ekstensi skrip Anda, atau jika Anda hanya menyukai URL cantik yang diakhiri dengan /, Anda mungkin ingin mendekatinya dari arah lain. Beri tahu nginx untuk membiarkan apa pun dengan ekstensi non-statis masuk ke apache. Sebagai contoh:

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

Saya menemukan bagian pertama dari cuplikan ini di: http://code.google.com/p/scalr/wiki/NginxStatic

lo_fye
sumber
Ini berfungsi dengan baik, meskipun saya masih mendapatkan kesalahan untuk file yang diperkecil (misalnya site.min.css dan main.min.js dll). Bagaimana cara menangkapnya di lokasi regex? @lo_fye
Garth