Nginx beberapa masalah lokasi

14

Saat ini saya mencoba memecah 3 aplikasi dari satu repositori menjadi 3, tetapi menjaga struktur url, jadi pada dasarnya lokasi yang berbeda di bawah domain yang sama harus dikirimkan oleh aplikasi yang berbeda.

Yang saya perjuangkan adalah bahwa salah satu aplikasi harus menjadi cadangan untuk url yang tidak ada, jadi jika yang pertama tidak cocok, dan yang kedua tidak cocok, maka yang ketiga harus menangani permintaan

Struktur yang saya miliki adalah:

/ etc / nginx / sites-enabled / main_site, di sini, selain dari server_name dan log yang saya punya include /etc/nginx/subsites-enabled/*, di mana saya punya 3 file konfigurasi, satu untuk masing-masing aplikasi.

Masing-masing dari 3 file konfigurasi berisi blok lokasi.

Saya sudah mencoba lookahead negatif di regex (pada dasarnya mencoba mengubah kode url yang ditangani aplikasi lain) tetapi gagal.

Jadi, untuk meringkas:

/ dan / komunitas harus dikirimkan oleh /etc/nginx/subsites-enabled/example.org/home (beberapa skrip perl)

/ berita harus disampaikan oleh /etc/nginx/subsites-enabled/example.org/news (wordpress)

segala sesuatu yang lain harus dikirimkan oleh /etc/nginx/subsites-enabled/example.org/app (aplikasi kue)

Bit perl bekerja dengan baik. Masalah yang saya alami adalah aplikasi ini mengambil alih berita (mungkin karena cocok. *), Saya sudah mencoba berbagai opsi (saya sudah melakukannya selama 2 hari) tetapi tidak satupun dari mereka menyelesaikan semua masalah (terkadang aset statis tidak akan berfungsi, dll).

Konfigurasi saya adalah:

/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 / subsitus-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 / subsitus-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
sumber
a) memposting konfigurasi Anda bersama dengan beberapa contoh di mana berbagai arahan ulang (termasuk yang untuk URL yang tidak ada) harus pergi. b) menggunakan try_files dengan blok lokasi bernama (menggunakan @awalan) yang memetakan ke aplikasi default Anda. Anda juga dapat mengatur error_page yang memetakan 404 ke lokasi yang ditentukan.
cyberx86
@ cyberx86 Saya menambahkan rincian lebih lanjut dan konfigurasi saya
Andrei Serdeliuc
Pandangan sekilas menyarankan beberapa hal: a) pencocokan regex lebih diutamakan daripada string konvensional - jadi blok aplikasi Anda akan cocok bukan blok berita Anda - coba location ^~ /news. b) untuk blok aplikasi Anda, Anda harus dapat melakukan location /(ini tidak sama dengan location = /, tetapi harus cocok dengan semua yang belum cocok. c) dalam beberapa kasus (terutama regex), pesanan itu penting - Anda mungkin ingin menggabungkan 3 file menjadi satu file dengan blok dalam urutan yang benar. Juga, gunakan try_files bukan !-e. Terakhir lihat wiki.nginx.org/HttpCoreModule#location .
cyberx86
Saya mencoba hampir semua variasi dari mereka, termasuk menggabungkan mereka ke dalam satu file (meskipun mereka harus terpisah karena mereka digunakan secara terpisah), tidak ada yang berfungsi. Berita baru saja ditangani oleh aplikasi.
Andrei Serdeliuc
Yah, saya pikir telah menyelesaikannya - sedikit lebih rumit dari yang saya perkirakan - tetapi tentu saja menyenangkan untuk disesuaikan dengan akal sehat. Terima kasih untuk teka-tekinya.
cyberx86

Jawaban:

45

Ada beberapa hal yang salah dengan konfigurasi Anda, dua yang relevan adalah:

  1. Jalur dalam blok lokasi masih menyertakan jalur yang cocok.
  2. Penulisan ulang dengan 'terakhir' melanjutkan dengan melihat melalui semua lokasi yang tersedia untuk pertandingan (mereka keluar dari blok lokasi saat ini).

Misalnya, ambil URL example.org/news/test.htm

  • The location /newsblok akan mencocokkannya
  • Path yang digunakan kemudian /news/test.htm- ini tidak berubah, hanya karena berada di blok lokasi
  • Menambahkan path ke document_root, Anda mendapatkan: /var/www/vhosts/news/news/test.htm
  • if (!-e $request_filename)Pernyataan Anda harus menangkap file yang tidak ada ini
  • Anda menulis ulang jalan menuju /index.php
  • Karena Anda menggunakan lastproses dimulai kembali (keluar dari blok lokasi)
  • /index.phpsekarang ditangkap oleh location /app block.

Masalah yang disebutkan di atas, dengan arahan root, diperparah ketika Anda pergi ke blok lokasi aplikasi Anda. Berbeda dengan blok 'berita', di mana Anda bisa saja menghapus 'berita' dari jalur (karena akan ditambahkan kembali), Anda tidak dapat melakukan ini untuk jalur aplikasi, yang diakhiri dengan 'webroot'.

Solusinya terletak pada aliasarahan. Ini tidak mengubah document_root, tetapi itu mengubah jalur file yang digunakan untuk melayani permintaan. Sayangnya, rewritedan try_filescenderung berperilaku sedikit tidak terduga dengan alias.

Mari kita mulai dengan contoh sederhana - tanpa PHP - hanya HTML dan blok Perl Anda - tetapi dengan struktur folder yang cocok dengan Anda (diuji pada 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 = / - hanya akan cocok dengan path root
  • location ^~ /community - akan mencocokkan setiap jalur yang dimulai dengan / komunitas
  • location ~ \.pl - akan cocok dengan semua file yang mengandung .pl
  • location ^~ /news - akan mencocokkan setiap jalur yang dimulai dengan / berita
  • location ^~ /app - Akan mencocokkan setiap jalur yang dimulai dengan / aplikasi
  • location / - akan mencocokkan semua jalur yang tidak cocok di atas

Anda harus dapat menghapus ^~- tetapi mungkin menawarkan sedikit peningkatan kinerja, karena berhenti mencari setelah kecocokan ditemukan.

Meskipun seharusnya merupakan hal yang sederhana untuk menambahkan kembali blok PHP, sayangnya, ada sedikit kesulitan - try_files(dan penulisan ulang Anda) tidak berakhir dengan meneruskan jalur yang diinginkan ke blok lokasi bersarang - dan menggunakan aliasketika hanya ekstensi tersebut. ditentukan dalam blok lokasi tidak berfungsi.

Salah satu solusinya adalah dengan menggunakan blok lokasi terpisah yang melakukan penangkapan bersama dengan arahan alias - itu tidak cukup elegan, tetapi sejauh yang saya tahu, itu berhasil (sekali lagi, diuji pada Nginx 1.0.12, CentOS 6 - dari Tentu saja, saya tidak mengatur CakePHP, Wordpress, dan Perl - Saya hanya menggunakan beberapa file PHP dan HTML di setiap folder)

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

Konfigurasi di atas, ambil yang sederhana di atas, dan buat dua perubahan:

  • Tambahkan dua blok lokasi:
    • location ~* ^/news/(.*\.php)$ - akan mencocokkan semua file yang berakhiran .php, dengan jalur yang dimulai dengan / news /
    • location ~* ^/app/(.*\.php)$ - akan mencocokkan semua file yang berakhiran .php, dengan jalur yang dimulai dengan / app /
  • Hapus ^~pencocokan - ini diperlukan agar dua blok lokasi yang ditambahkan dapat cocok dengan jalur (jika tidak, pencocokan akan berhenti di blok / news atau / aplikasi).

Perlu dicatat bahwa urutan pencocokan lokasi sangat penting di sini:

  • Pertandingan yang tepat terlebih dahulu (menggunakan =)
  • Cocok dengan yang ^~kedua
  • Mencocokkan blok regex
  • String konvensional - hanya jika tidak ditemukan regex yang cocok

Regex yang cocok akan menggantikan string lurus!

Poin penting yang disebutkan adalah ketika tangkapan digunakan dengan alias, seluruh URL diganti - bukan hanya folder utama. Sayangnya, ini berarti $fastcgi_script_namedibiarkan kosong - jadi, saya telah menggunakan di $1atas sebagai gantinya.

Saya yakin Anda perlu membuat beberapa perubahan, tetapi premis dasar harus fungsional. Anda harus dapat memisahkan blok menjadi beberapa file sesuai kebutuhan - pemesanan tidak akan memengaruhi konfigurasi.

cyberx86
sumber
2
Kawan, kuharap aku bisa mengalahkanmu 100 kali. Kamu murni luar biasa. Terima kasih!
Andrei Serdeliuc