Cara menulis ulang Nginx untuk mendapatkan url bersih dari nomor halaman

Jan 15 2020

Baru-baru ini kami telah pindah ke Nginx dari Apache, Di bawah apache, biasanya sangat mudah, cukup taruh beberapa hal di .htaccess dan selesai.

RewriteEngine on
RewriteBase /

# only rewrite if the requested file doesn't exist
RewriteCond %{REQUEST_FILENAME} !-s

# pass the rest of the request into index.php to handle
RewriteRule ^(.*)$ /index.php/$1 [L]

Hal di atas sangat bagus untuk membersihkan URL dan membiarkan index.php menangani semua permintaan. tetapi di Nginx kami perlu menulis ulang setiap URL unik di blok lokasi. Namun ini tidak 'otomatis' seperti Apache.

Beberapa contoh blok lokasi penulisan ulang kami

location / {
try_files $uri $uri/ /index.php;
}

location /p {
rewrite ^/p(?:/([a-z_]+))?$ /index.php?p=$1 last;
rewrite ^/p/all_articles/user/(.*)?$ /index.php?p=all_articles&user=$1 last;
try_files $uri $uri/ /index.php;
}

location /about_us {
rewrite ^/about_us /index.php?about_us last;
try_files $uri $uri/ /index.php;
}

location /search {
rewrite ^/search/(.*) /index.php?search=$1; rewrite ^/search/(.*)/page/(.*)?$ /index.php?search=$1&page=$2 last;
try_files $uri $uri/ /index.php;
}

location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

di atas berfungsi dengan baik di URL yang bersih, tetapi ketika kita perlu mendapatkan halaman misalnya

/ p / all_articles / pengguna / ABC / halaman / 2

/index.php?p=all_articles&user=ABC&page=2

kami telah mencoba

rewrite ^/p/all_articles/user/(.*)/pg(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&pg=$2 last;

ini hanya berfungsi ketika kami menempatkan di blok lokasi terpisah

location /page/all_articles {
rewrite ^/p/all_articles/user/(.*)/pg(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&pg=$2 last; try_files $uri $uri/ /index.php;
}

dan ketika melakukannya, itu tidak akan membiarkan

/ p / all_articles / pengguna / ABC

untuk memuat.

juga, halaman hasil pencarian tidak akan berfungsi sama sekali.


Masalah lain yang kami temukan ada di folder .htaccess

Order deny,allow
Deny from all
Options -Indexes

Di bawah apache, ini akan mencegah akses apa pun ke folder dan file itu kecuali untuk skrip php. Kami sudah mencoba,

location /(data|img)/ {
   deny all;
   return 404;
}

Itu memang memblokir akses ke folder tetapi, jika Anda menentukan nama file, itu akan tetap berfungsi, tanpa menolak akses misalnya;

/data/backup_01012020.zip di bawah apache .htaccess, hanya pengguna tertentu yang diizinkan untuk mengakses ini, saat masuk. dan di luar itu, apache akan menolak akses apa pun. Tetapi di bawah nginx meskipun memberikan 404 ketika mencoba mengakses / data /. Bahkan ketika Anda tidak masuk, itu akan segera menyajikan file backup_01012020.zip.

Sekarang kita tidak tahu apa yang bisa kita lakukan, yang dulu sangat mudah dengan apache. Aplikasi kita didasarkan pada PHP dan index.php mampu menangani semua permintaan URL yang bersih. Akan sangat bagus jika Nginx meneruskan semua permintaan ke indeks dan membiarkannya menangani alih-alih banyak penulisan ulang dan blok lokasi. Bantuan apa pun akan sangat bagus.

Jawaban

2 PiotrP.Karwasz Jan 15 2020 at 07:07

Anda mungkin tertarik dengan pertanyaan dengan tag rewrite , karena mengandung banyak variasi dari masalah Anda.

Aturan penulisan ulang Apache Anda:

RewriteRule ^(.*)$ /index.php/$1 [L]

menambahkan seluruh URI permintaan ke /index.php. Di nginx , jalur URI (dinormalisasi) tersedia di variabel $ uri . Jika Anda membutuhkan argumen kueri juga, Anda dapat menggunakan $ request_uri sebagai gantinya.

Terjemahan ketat dari aturan penulisan ulang Anda adalah:

location / {
    # Size zero static files are served.
    # I don't believe that is an issue.
    try_files $uri /index.php$request_uri;
}
# If no other .php files are accessible a prefix location of '/index.php/'
# is safer.
location /index.php/ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
    # Probably duplicates the contents of fastcgi-php.conf
    # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    # include fastcgi_params;
}

denyPerintah Anda di /(data|img)/lokasi tidak berfungsi, karena Anda menggunakan pencocokan awalan, bukan pencocokan ekspresi reguler:

location ~ ^/(data|img)/ {
   # Only one is required
   deny all;
   # return 404;
}
HelenSaepp Jan 17 2020 at 00:04

Solusi untuk menulis ulang

location /search {
rewrite ^/search/(.*)/page/(.*)?$ /index.php?search=$1&page=$2 last; rewrite ^/search/(.*) /index.php?search=$1 last;
try_files $uri $uri/ /index.php;
}

location /p/all_articles {
rewrite ^/p/all_articles/user/(.*)/page(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&page=$2 last; rewrite ^/p/all_articles/user/(.*)?$ /index.php?p=all_articles&user=$1 last; try_files $uri $uri/ /index.php;
}

Perhatikan, yang saya lakukan hanyalah bertukar jalur. Penghargaan untuk Richard Smith


Terima kasih kepada Piotr P. Karwasz , untuk solusi lainnya, ini mungkin membantu seseorang yang skripnya 100% kompatibel untuk menangani URL bersih sendiri.

location / {
    # Size zero static files are served.
    # I don't believe that is an issue.
    try_files $uri /index.php$request_uri; } # If no other .php files are accessible a prefix location of '/index.php/' # is safer. location /index.php/ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; # Probably duplicates the contents of fastcgi-php.conf # fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    # include fastcgi_params;
}

solusi di atas adalah cara untuk pergi selama skrip Anda berfungsi dengan URL bersih 100%. Di sini, Anda tidak perlu meletakkan 100 blok lokasi penulisan ulang, dan nginx akan menambahkan seluruh URI permintaan ke /index.php yang sangat menarik dan membantu, mungkin ini adalah solusi sebenarnya, tetapi dalam kasus saya skrip saya tidak 100 % kompatibel dengan ini. Tetap saja ini adalah solusi yang bagus dan cerdas.


Soution untuk mencegah folder, akses file

location ~ ^/(data|img)/ {
   # Only one is required
   deny all;
   # return 404;
}

Penghargaan untuk Piotr P. Karwasz menunjukkan, deny alltelah ditimpa oleh sesuatu, setelah blok server bersih itu menyelesaikan masalah. Juga pastikan untuk menggunakan salah satu deny all;atau return 404;tetapi tidak bersamaan.