Skip to content

Penguji nginx location — mengapa blok itu menang

Blok location nginx mana yang menang — dan mengapa yang lain kalah. Penguji gratis untuk =, ^~, ~ dan ~*, sepenuhnya di browser Anda.

Tanpa Pelacakan Berjalan di Browser Gratis
Konfigurasi Anda diurai secara lokal di browser dan tidak pernah diunggah. Konfigurasi server memuat hostname upstream dan blok autentikasi, jadi buka panel Network dan lihat ia tetap sunyi — atau putuskan koneksi sekalian.
Coba kesalahan konfigurasi nyata
Location terpilih
~* \.(gif|jpg|jpeg)$

Regex pertama, menurut urutan konfigurasi, yang cocok. Panjang tidak relevan.

Apa yang sebenarnya dicocokkan nginx
Target permintaan
/documents/1.jpg
$uri ternormalisasi
/documents/1.jpg
Query string $args

Pencocokan hanya berjalan terhadap path ternormalisasi. Query string dipisahkan lebih dulu dan tidak pernah ikut serta.

Kenapa blok itu menang
Kenapa blok itu menang
Baris location Tahap Hasil Alasan
2 = / Persis Tidak cocok Location = menuntut seluruh URI sama persis, bukan sekadar diawali olehnya.
3 / Prefiks Cocok tetapi lebih pendek Ia cocok, tetapi prefiks lain mencakup lebih banyak karakter.
4 /documents/ Prefiks Cocok tetapi lebih pendek Ia cocok, tetapi prefiks lain mencakup lebih banyak karakter.
5 ^~ /images/ Prefiks Tidak cocok URI tidak diawali prefiks ini.
6 ~* \.(gif|jpg|jpeg)$ Regex Terpilih Regex pertama, menurut urutan konfigurasi, yang cocok. Panjang tidak relevan.

Modifier location nginx: =, ^~, ~ dan ~* dibandingkan

Modifier location nginx: =, ^~, ~ dan ~* dibandingkan
Modifier Sintaks Cocok berdasarkan Urutan Menghentikan regex Penggunaan umum
= location = /path Kesamaan 1 Ya Path yang sering diakses seperti / — kecocokan paling cepat yang mungkin.
^~ location ^~ /path Diawali 2 Ya Direktori yang tidak boleh diserahkan ke regex, misalnya direktori upload.
~ location ~ regex Regex PCRE 3 Tidak Perutean berdasarkan ekstensi ketika huruf besar-kecil berpengaruh.
~* location ~* regex Regex PCRE 3 Tidak Perutean berdasarkan ekstensi ketika huruf besar-kecil tidak berpengaruh.
(tidak ada) location /path Diawali 4 Tidak Perutean umum berdasarkan path.
@ location @name Internal saja Tidak Fallback untuk error_page dan try_files.

Kolom urutan bukan peringkat sederhana. Location prefiks baru menghentikan evaluasi regex ketika ia membawa ^~ dan ia sendiri adalah kecocokan terpanjang — persis itulah sebabnya blok ^~ kadang tampak tidak berbuat apa-apa.

Prioritas location nginx: urutan penyelesaiannya

Prioritas location nginx: urutan penyelesaiannya
# Tahap Mengakhiri pencarian Apa yang terjadi
1 Normalisasi Tidak Dekode persen, penyelesaian . dan .., garis miring berulang dimampatkan. Query string dipisahkan di sini dan tidak pernah ikut dalam pencocokan.
2 Persis Ya location = /path, dibandingkan berdasarkan kesamaan. Satu kena langsung mengakhiri pencarian.
3 Redirect otomatis Ya Location proxy yang namanya adalah URI ditambah satu garis miring. nginx membalas 301 dan tidak pernah sampai ke regex.
4 Prefiks Tidak Setiap prefiks yang cocok dibandingkan dan yang terpanjang diingat. Urutan di konfigurasi diabaikan.
5 Bersarang Tidak Prefiks pemenang ditelusuri ke dalam. Regex bersarang diuji sebelum level induk.
6 Regex Ya Regex diuji sesuai urutan konfigurasi dan kecocokan pertama menang. Regex yang lebih panjang atau lebih spesifik tetapi ditulis belakangan tidak pernah berjalan.
7 Fallback Ya Tidak ada regex yang cocok, jadi prefiks yang diingat sebelumnya dipakai.
Urutan pencocokan, pemotongan oleh ^~, penurunan ke location bersarang, perilaku redirect otomatis, dan normalisasi URI dicocokkan dengan kode sumber nginx sendiri dan dikonfirmasi dengan menjalankan konfigurasinya di nginx 1.27.5. — Tim Engineering Go Tools · Jul 22, 2026

Aturan pemilihan di halaman ini diverifikasi terhadap nginx 1.27.5 yang benar-benar berjalan, bukan diambil dari tulisan tangan kedua, dan mesinnya dicakup uji unit yang diturunkan dari eksekusi tersebut.

Pencocokan location nginx: jawaban singkat

Apakah nginx memproses location regex sebelum kecocokan prefiks?

Tidak — prefiks diperiksa lebih dulu, tetapi regex yang cocok tetap menang. nginx memeriksa semua location prefiks lebih dulu dan mengingat kecocokan terpanjang, lalu mengevaluasi location regex sesuai urutan kemunculannya di berkas. Regex pertama yang cocok akan menang. Jika tidak ada regex yang cocok, location prefiks yang diingat tadi dipakai. Satu-satunya pengecualian adalah ^~: bila prefiks cocok terpanjang membawanya, fase regex dilewati sepenuhnya.

Apakah urutan blok location berpengaruh di nginx?

Hanya untuk location regex. Location prefiks — termasuk = dan ^~ — dipilih berdasarkan kecocokan terpanjang, jadi urutannya di berkas tidak relevan. Location regex diuji dari atas ke bawah dan kecocokan pertama menang, sehingga memindahkan satu blok regex mengubah blok mana yang berjalan. Regex yang lebih spesifik tetapi ditaruh di bawah regex yang lebih luas tidak akan pernah dieksekusi.

Apa yang sebenarnya dilakukan modifier ^~?

Ia menghentikan nginx setelah kecocokan prefiks, bukan menaikkan prioritas. Jika location prefiks cocok yang terpanjang membawa ^~, nginx melewati fase regex dan memakai blok itu. Ia tidak membuat prefiks jadi lebih panjang maupun menempatkannya di atas prefiks lain — ia hanya menekan evaluasi regex. Karena itulah blok ^~ tampak tidak berbuat apa-apa ketika ada prefiks biasa yang lebih panjang yang juga cocok: yang lebih panjang itulah yang diingat, dan ia tidak menekan apa pun.

Apakah location /static sama dengan location /static/?

Tidak — /static juga cocok dengan /staticfoo. Pencocokan prefiks adalah perbandingan string biasa, bukan batas segmen path, jadi location /static juga melayani /staticfiles dan /static-backup. Terpisah dari itu, ketika /static/ dipakai bersama proxy_pass, permintaan ke /static tanpa garis miring di akhir dijawab redirect 301 ke /static/ sebelum satu pun regex dipertimbangkan.

Apakah nginx mendekode %2F dan memampatkan garis miring ganda sebelum pencocokan?

Ya — pencocokan berjalan terhadap URI hasil normalisasi, bukan permintaan mentah. nginx mendekode %XX, menyelesaikan . dan .. serta memampatkan garis miring berulang sebelum memilih location. %2F yang terdekode menjadi pemisah sungguhan dan ikut dalam penyelesaian itu, sehingga /a/b%2F..%2Fzz dicocokkan sebagai /a/zz. Query string dipisahkan lebih dulu dan sama sekali tidak pernah ikut dalam pencocokan.

Apa itu blok location nginx?

Blok location memberi tahu nginx apa yang harus dilakukan terhadap permintaan yang URI-nya cocok dengan sebuah pola. Satu blok server biasanya memuat beberapa location, dan bagian yang menarik bukan apa yang dilakukan masing-masing, melainkan yang mana yang dipilih nginx — karena aturan pemilihannya bukan aturan yang diduga kebanyakan orang.

Ada lima bentuk. location = /path cocok hanya ketika seluruh URI sama persis. location /path cocok dengan URI mana pun yang diawali karakter tersebut. location ^~ /path adalah perbandingan prefiks yang sama dengan satu efek tambahan. location ~ regex dan location ~* regex menerapkan pola PCRE, dengan dan tanpa membedakan huruf besar-kecil. location @name sama sekali tidak ikut dalam pencocokan URI dan hanya ada sebagai sasaran try_files dan error_page.

Pemilihan berjalan bertahap. Pertama URI dinormalisasi: persen didekode, . dan .. diselesaikan, garis miring berulang dimampatkan, query string dipisahkan. Lalu location = yang sama dengan URI langsung mengakhiri pencarian. Kemudian semua prefiks yang cocok dibandingkan dan yang terpanjang diingat — urutan di konfigurasi sama sekali tidak berperan di sini. Jika prefiks yang diingat itu membawa ^~, nginx berhenti dan memakainya. Kalau tidak, location regex diuji sesuai urutan kemunculannya di berkas, dan kecocokan pertama yang menang, sespesifik apa pun regex berikutnya. Kalau tidak ada yang cocok, prefiks yang diingat tadi dipakai.

Dua aturan itu menarik ke arah berlawanan, dan di situlah kebingungannya bermukim: prefiks dipilih berdasarkan panjang tanpa memedulikan urutan, regex berdasarkan urutan tanpa memedulikan panjang. Konfigurasi yang terbaca benar dari atas ke bawah tetap bisa merutekan permintaan ke tempat yang tidak Anda maksudkan, dan sebanyak apa pun Anda membacanya ulang, itu tidak akan tampak. Halaman ini memutar ulang seluruh rangkaian tadi terhadap konfigurasi Anda sendiri dan menunjukkan di mana setiap blok gugur.

# From the nginx documentation. Which block serves each request?
server {
    location = /                   { }   # A
    location /                     { }   # B
    location /documents/           { }   # C
    location ^~ /images/           { }   # D
    location ~* \.(gif|jpg|jpeg)$  { }   # E
}

#   /                        -> A   exact match, search ends here
#   /index.html              -> B   no regex matched, longest prefix used
#   /documents/document.html -> C   longer prefix than B
#   /images/1.gif            -> D   ^~ won the prefix stage, regex skipped
#   /documents/1.jpg         -> E   regex beats the longer prefix C

# The last two lines are the whole lesson: identical-looking prefixes
# behave differently because only one of them carries ^~.

Fitur utama

Setiap blok yang kalah, lengkap dengan tahap ia tersingkir

Setiap location yang Anda tulis mendapat satu baris: cocok tetapi lebih pendek, dilewati karena prefiks ^~ menang, tidak terjangkau karena regex sebelumnya sudah cocok, atau sekadar tidak cocok. Mengetahui kenapa yang lain kalah biasanya justru itulah yang menuntaskan persoalannya.

Rantai keputusan empat tahap, diputar ulang

Normalisasi, kecocokan persis, ingatan prefiks terpanjang, pemotongan oleh ^~, regex sesuai urutan berkas, dan fallback ditampilkan sebagai langkah-langkah terpisah terhadap konfigurasi Anda sendiri, bukan diuraikan secara abstrak.

Pemotongan oleh ^~ dibuat terlihat

Ketika prefiks ^~ menekan fase regex, setiap regex yang dilewati diberi label dilewati alih-alih menghilang tanpa jejak — dan ketika ^~ gagal berlaku karena prefiks biasa yang lebih panjang menang, itu pun ditampilkan.

Location bersarang diselesaikan, bukan diratakan

nginx turun ke dalam prefiks pemenang lalu menelusuri anak-anaknya, jadi regex bersarang berjalan lebih dulu daripada regex level induk. Blok bersarang mempertahankan indentasinya di tabel supaya strukturnya tetap terbaca.

Sintaks khas PCRE dideteksi sejak awal

Browser menjalankan regex ECMAScript, bukan PCRE. Grup atomik, kuantifier posesif, kelas POSIX, dan escape seperti \A dan \K ditandai alih-alih dievaluasi keliru tanpa suara, sehingga jawaban salah yang terdengar meyakinkan tidak pernah disajikan sebagai fakta.

Tidak ada yang diunggah — semuanya jalan di browser Anda

Konfigurasi server memuat hostname upstream, port internal, dan aturan autentikasi. Parsing di sini murni pekerjaan string, tanpa dependensi dan tanpa panggilan jaringan, diverifikasi oleh uji kontrak otomatis pada setiap build.

Cara lain menjawab pertanyaan ini

nginx -T

Baris perintah

Menumpahkan konfigurasi yang sudah sepenuhnya diselesaikan, sangat berguna untuk tahu apa yang benar-benar termuat. Ia tidak memberi tahu location mana yang dipilih untuk sebuah URI — itulah celah yang diisi halaman ini.

error_log ... debug

Server berjalan

Jawaban paling otoritatif yang ada: baris "using configuration" menyebut blok yang benar-benar dipilih nginx. Butuh root, satu reload, dan server yang bisa Anda jangkau — jadi ia menjawab setelah rilis, bukan sebelumnya.

Pemeriksa sintaks konfigurasi

Layanan hosted

Kuat untuk lint seluruh berkas dan aturan keamanan. Umumnya berjalan di sisi server, yang berarti mengunggah konfigurasi berisi hostname internal dan path sertifikat.

Membaca dokumentasi

Rujukan

Dokumentasi nginx menyatakan algoritmenya dengan tepat dan layak dibaca sekali. Menerapkannya secara manual pada delapan blok dan satu URI adalah titik masuknya kesalahan, karena dua aturannya menarik ke arah berlawanan.

Contoh pencocokan location nginx

Ekspresi reguler mengalahkan prefiks yang lebih panjang

location /documents/  ·  location ~* \.(gif|jpg|jpeg)$  ·  GET /documents/1.jpg
~* \.(gif|jpg|jpeg)$ wins

Prefiks /documents/ cocok dan merupakan prefiks terpanjang di berkas itu, jadi nginx mengingatnya — lalu tetap mengevaluasi regex dan menyerahkan permintaan ke regex pertama yang cocok. Panjang kalah oleh fase regex. Seandainya prefiks itu ditulis ^~ /documents/, tidak ada regex yang akan dijalankan sama sekali. Ini contoh dari dokumentasi nginx, dan inilah satu contoh yang paling berguna untuk dihafal.

Direktori upload yang mengeksekusi PHP

location /uploads/  ·  location ~ \.php$ { fastcgi_pass ... }  ·  GET /uploads/evil.php
~ \.php$ wins — the upload lands in the interpreter

Prefiks /uploads/ cocok, tetapi prefiks biasa tidak menghentikan fase regex, sehingga berkas yang diunggah orang lain langsung diserahkan ke PHP-FPM. Menulis location ^~ /uploads/ memotong fase regex dan menutup celah itu. Ini bukan skenario khayalan: inilah bentuk di balik deretan panjang laporan upload-ke-RCE, dan jarak antara rentan dan aman cuma dua karakter.

^~ yang diam-diam tidak berbuat apa-apa

location ^~ /a/  ·  location /a/b/  ·  location ~ \.php$  ·  GET /a/b/x.php
~ \.php$ wins — the ^~ never applied

^~ hanya menekan fase regex jika ia sendiri adalah prefiks cocok yang terpanjang. Di sini /a/b/ lebih panjang, jadi itulah yang diingat nginx, dan modifier biasanya membiarkan fase regex berjalan. Blok ^~ masih ada di berkas, masih terlihat protektif, dan sama sekali tidak berpengaruh pada permintaan ini. Membaca konfigurasi dari atas ke bawah tidak akan mengungkapnya; membandingkan panjang prefiks akan.

/static juga menangkap /staticfoo

location /static  ·  location /static/  ·  GET /staticfoo
/static wins

Pencocokan prefiks membandingkan karakter, bukan segmen path. /staticfoo diawali /static, jadi cocok, sedangkan /static/ sama sekali tidak cocok karena URI tidak punya garis miring di posisi itu. Apa pun yang bisa diakses di bawah path yang sekadar diawali huruf yang sama akan dilayani blok tersebut — begitulah aturan /static berakhir melayani /static-backup.

Regex pertama yang menang, bukan yang terbaik

location ~ ^/a  ·  location ~ ^/a/b/c$  ·  GET /a/b/c
~ ^/a wins; ~ ^/a/b/c$ is unreachable

Regex dievaluasi sesuai urutan kemunculannya di berkas dan kecocokan pertama mengakhiri pencarian. Blok kedua lebih spesifik dan cocok persis dengan URI ini, tetapi tidak akan pernah berjalan — untuk permintaan apa pun. Location prefiks dipilih berdasarkan panjang tanpa memedulikan urutan; location regex dipilih berdasarkan urutan tanpa memedulikan spesifisitas. Tertukar antara dua aturan itu adalah alasan lazim sebuah aturan "berhenti bekerja" setelah ada yang merapikan berkas.

Traversal terenkode diselesaikan sebelum pencocokan

location /a/  ·  location /b/  ·  GET /a/b%2F..%2Fzz
$uri becomes /a/zz, so /a/ wins

nginx mendekode persen, menyelesaikan . dan .. serta memampatkan garis miring berulang sebelum satu pun location dikonsultasikan. %2F terdekode menjadi pemisah sungguhan lalu ikut dalam penyelesaian itu, sehingga target ini tidak tetap berada di dalam /a/b/ — ia mendarat di /a/zz. Mencocokkan terhadap target yang Anda ketik alih-alih $uri hasil normalisasi memberi jawaban yang salah di sini.

Cara memakai penguji location nginx

  1. 1

    Tempel blok server

    Masukkan satu blok server utuh, atau cukup blok location yang sedang Anda pikirkan. Location bersarang dipahami, dan nomor baris aslinya dipertahankan supaya tabelnya cocok dengan berkas Anda.

  2. 2

    Masukkan URI permintaan

    Ketik path persis seperti yang tiba di jaringan, termasuk enkode persen dan query string. Tiga baris di atas tabel menunjukkan bagaimana path itu dinormalisasi sebelum pencocokan.

  3. 3

    Baca pemenangnya, lalu yang kalah

    Kartu vonis menyebut blok terpilih dan alasannya dalam satu baris. Tabel keputusan di bawahnya menjelaskan setiap blok lain: di tahap mana ia tersingkir dan kenapa.

  4. 4

    Periksa diagnostiknya

    Regex tanpa jangkar, prefiks tanpa garis miring di akhir, ^~ yang membawa pola regex, duplikat yang tidak terjangkau, dan direktori upload yang bisa dijangkau regex PHP semuanya dilaporkan.

  5. 5

    Bagikan state persisnya

    Salin tautan mengenkode konfigurasi dan URI ke dalam fragmen URL, sehingga rekan Anda membuka persis apa yang sedang Anda lihat. Fragmen tidak pernah dikirim ke server.

Kesalahan umum pada location nginx

Mengira ^~ mengalahkan prefiks yang lebih panjang

^~ hanya diperiksa pada prefiks yang sudah menang berdasarkan panjang. Prefiks biasa yang lebih panjang menang lebih dulu, lalu fase regex berjalan seolah ^~ itu tidak ada.

✗ Salah
location ^~ /a/ { }
location /a/b/ { }
location ~ \.php$ { }
# /a/b/x.php -> ~ \.php$
✓ Benar
location ^~ /a/ { }
location ^~ /a/b/ { }
location ~ \.php$ { }
# /a/b/x.php -> ^~ /a/b/

Prefiks tanpa garis miring di akhir yang menyambar path sebelah

Pencocokan prefiks membandingkan karakter, bukan segmen path, jadi blok itu juga melayani setiap path sebelah yang diawali huruf yang sama.

✗ Salah
location /static { root /var/www; }
# also serves /staticfoo and /static-backup
✓ Benar
location /static/ { root /var/www; }
location = /static { return 301 /static/; }

Menaruh regex spesifik di bawah regex luas

Regex diuji sesuai urutan berkas dan kecocokan pertama mengakhiri pencarian, jadi blok yang lebih presisi tidak pernah dieksekusi untuk permintaan apa pun.

✗ Salah
location ~ ^/api { }
location ~ ^/api/v2/users$ { }
# the second is unreachable
✓ Benar
location ~ ^/api/v2/users$ { }
location ~ ^/api { }

Menulis regex setelah ^~

^~ menerima prefiks literal. nginx memuat berkasnya tanpa protes dan blok itu memang tidak pernah cocok dengan apa pun, sehingga sulit terlihat saat review.

✗ Salah
location ^~ "\.php$" { deny all; }
✓ Benar
location ~ \.php$ { deny all; }

Mengira query string ikut dalam pencocokan

Query string dipisahkan saat normalisasi, jadi location tidak pernah bisa mencocokkannya. Baca $arg_name di dalam blok saja.

✗ Salah
location /search?q= { }
# never matches anything
✓ Benar
location /search {
    if ($arg_q = "") { return 400; }
}

Apa yang bisa Anda lakukan dengan penguji location nginx

Memeriksa konfigurasi sebelum masuk produksi
Telusuri perutean blok server yang sudah Anda ubah tetapi belum dirilis. Kegagalan yang tertangkap di sini adalah yang hanya muncul pada bentuk URI tertentu, persis jenis yang biasanya lolos dari smoke test setelah reload.
Mencari tahu kenapa sebuah aturan berhenti bekerja
Regex yang dulu berjalan dan kini tidak hampir selalu jadi korban urutan: ada yang cocok lebih dulu, atau muncul ^~ di atasnya. Tabelnya menandai blok itu tidak terjangkau dan menyebut blok yang menyambar permintaannya.
Mengaudit direktori upload atau media
Muat preset yang mereproduksi pola upload-lalu-dieksekusi, lalu tempel path Anda sendiri. Kalau ada regex PHP yang menyambar permintaan di dalam direktori yang bisa ditulisi, diagnostiknya akan menyatakannya dan menyebut kedua bloknya.
Menutup komentar review dengan bukti
Salin tautan menangkap konfigurasi dan URI persisnya di fragmen URL. Menjatuhkannya ke pull request menukar perdebatan soal prioritas dengan tabel keputusan yang bisa dijalankan ulang siapa saja.
Mengajarkan algoritme pemilihannya
Kedua tabel rujukan adalah materi statis yang bisa diindeks dan bisa Anda tunjuk, dan chip preset memperagakan setiap jebakannya tanpa perlu merusak server. Contoh ^~ khususnya cenderung menutup perdebatan dengan cepat.

Bagaimana pemilihan location nginx bekerja

Normalisasi terjadi sebelum satu pun location dikonsultasikan
URI didekode dari persen, segmen . dan .. diselesaikan, garis miring berulang dimampatkan, dan baru setelah itu sebuah location dipilih. %2F yang terdekode menjadi pemisah sungguhan dan ikut dalam penyelesaian itu, sehingga /a/b%2F..%2Fzz dicocokkan sebagai /a/zz. Tiga karakter terdekode menjadi pengecualian dan tetap literal: %25, %23, dan %3F — itu sebabnya /a%3Fx=1 punya tanda tanya di path-nya dan query string kosong. Di sini + bukan spasi; hanya %20 yang spasi. Traversal yang naik di atas root dan escape tidak valid sama-sama ditolak dengan 400 sebelum pencocokan dimulai.
Panjang prefiks yang menentukan, bukan urutan di konfigurasi
Setiap location prefiks yang cocok dibandingkan dan yang terpanjang menang, entah ia muncul paling awal atau paling akhir di berkas. Perbandingannya per karakter, bukan per segmen path, jadi /static cocok dengan /staticfoo. Pemenangnya diingat, bukan langsung dipakai, karena fase regex masih bisa menganulirnya.
^~ menekan regex; ia tidak menaikkan prioritas
Modifier ini hanya diperiksa pada prefiks yang sudah menang berdasarkan panjang. Kalau ada prefiks biasa yang lebih panjang yang juga cocok, prefiks itulah yang diingat dan fase regex berjalan seperti biasa — blok ^~ sama sekali tidak berpengaruh pada permintaan tersebut. Menaruh ^~ pada location bersarang tidak melindungi dari regex yang dideklarasikan di level luar, dan ia tidak pernah menekan regex yang bersarang di dalam bloknya sendiri.
Regex berjalan sesuai urutan berkas dan kecocokan pertama mengakhiri pencarian
nginx menyimpan location regex sesuai urutan penulisannya dan tidak mengurutkannya. Spesifisitas, panjang, dan penjangkaran tidak memengaruhi mana yang diuji lebih dulu, jadi pola presisi yang ditaruh di bawah pola luas adalah konfigurasi mati. Location regex yang cocok tetap ditelusuri ke dalam, sehingga location bersarang di dalamnya diperiksa sesudahnya.
PCRE dan ECMAScript bukan bahasa yang sama
nginx mengompilasi regex location dengan PCRE, tanpa mode UTF maupun multiline, jadi polanya bekerja pada byte dan ^ hanya berjangkar di awal URI. Satu perbedaan punya bobot keamanan: $ pada PCRE juga cocok tepat sebelum baris baru di akhir, sehingga URI yang berakhir dengan %0A tetap memenuhi \.php$ padahal mesin JavaScript akan menolaknya. Perilaku itu ditiru di sini dan dilaporkan, karena inilah cara yang sudah dikenal untuk menyelinap lewat aturan yang bersandar pada ekstensi berkas.

Praktik terbaik location nginx

Lindungi direktori yang bisa ditulisi dengan ^~, bukan prefiks biasa
Setiap direktori yang menerima upload butuh location ^~ /uploads/ supaya fase regex tidak bisa menyerahkan berkas tersimpan ke interpreter. Prefiks biasa terlihat setara padahal tidak.
Beri garis miring di akhir pada prefiks direktori
Tulis location /static/ alih-alih location /static, kecuali Anda memang sengaja ingin /staticfoo dan /static-backup dilayani blok yang sama. Tambahkan location = /static terpisah bila path polosnya juga perlu ditangani.
Urutkan regex dari yang paling spesifik ke yang paling umum
Kecocokan pertama yang menang, jadi pola luas di atas pola presisi membuat yang presisi tidak terjangkau. Menjaga jumlah regex tetap sedikit dan mengurutkannya dengan sengaja lebih mudah dirawat daripada menalar tumpang tindihnya belakangan.
Jangkarkan regex yang dimaksudkan mencocokkan prefiks path
location ~ /admin mencari di titik mana pun dalam URI dan cocok dengan /public/admin/x. Tulis ~ ^/admin kalau yang Anda maksud adalah bagian awal. Menjangkarkan hanya di akhir itu wajar dan benar untuk perutean berdasarkan ekstensi.
Cek ulang perutean setelah setiap penataan ulang
Memindahkan blok aman untuk prefiks dan mengubah perilaku regex. Karena diff yang cuma menata ulang baris terlihat tidak berbahaya saat review, menjalankan ulang URI yang terdampak adalah cara termurah untuk menangkapnya.

Pertanyaan yang sering diajukan tentang penguji location nginx

Bagaimana cara mengetahui location mana yang dipilih nginx?
Tempel konfigurasi dan URI permintaan ke penguji ini untuk melihat blok pemenang dan alasan setiap blok lain tersingkir. Di server yang sedang berjalan, tambahkan error_log /var/log/nginx/debug.log debug; lalu cari baris "using configuration", yang menyebut nama location terpilih. Kedua pendekatan menjawab pertanyaan berbeda: log memberi tahu apa yang dilakukan server hidup, sedangkan halaman ini memberi tahu apa yang akan dilakukan konfigurasi yang belum Anda rilis.
Kenapa regex location nginx saya tidak bekerja?
Biasanya karena salah satu dari tiga hal, dan tabel keputusan menyebut yang mana. Ada regex lebih awal yang sudah cocok, jadi punya Anda tidak pernah dijalankan — regex diuji sesuai urutan berkas dan kecocokan pertama menang. Atau prefiks cocok terpanjang membawa ^~, yang melewati fase regex sepenuhnya. Atau regexnya benar tetapi URI-nya bukan yang Anda kira: pencocokan berjalan terhadap path hasil normalisasi, setelah dekode persen dan penyelesaian .., dengan query string sudah dibuang.
Kenapa kecocokan persis saya tidak terpicu?
Location = menuntut seluruh URI sama persis, bukan sekadar diawali polanya. location = /a/ tidak cocok dengan /a, dan location = /a tidak cocok dengan /a/b. Garis miring di akhir di sini adalah karakter biasa, jadi kedua bentuk itu string yang berbeda. Ketika location persis memang cocok, pencarian langsung berhenti dan tidak ada lagi yang dibandingkan.
Apakah nginx mencocokkan query string di dalam blok location?
Tidak. Query string dipisahkan saat normalisasi dan pemilihan location hanya berjalan terhadap path. Itu sebabnya location = /a cocok dengan permintaan ke /a?x=/b. Kalau Anda perlu bercabang berdasarkan sebuah parameter, Anda harus membaca $arg_name atau $args di dalam blok. Satu kehalusan yang layak diketahui: %3F terdekode menjadi tanda tanya literal yang tetap tinggal di path, jadi /a%3Fx=1 punya query string kosong dan path yang mengandung ?.
Bisakah saya memakai sintaks regex JavaScript di location nginx?
Tidak — nginx memakai PCRE, dan perbedaannya penting. Halaman ini berjalan di browser Anda, tempat hanya ekspresi reguler ECMAScript yang ada, jadi konstruksi khas PCRE dideteksi dan ditandai alih-alih dievaluasi keliru tanpa suara: grup atomik, kuantifier posesif, modifier inline seperti (?i), kelas POSIX seperti [[:alpha:]], dan escape seperti \A serta \K yang dibaca JavaScript begitu saja sebagai huruf biasa. Ketika sebuah location ditandai, kandidat sisanya tetap dievaluasi mengikuti urutan nginx, tetapi vonis untuk blok itu perlu dicek di server sungguhan. Kalau Anda sedang menyusun polanya sendiri, penguji regex membahas sintaks ECMAScript secara mendalam.
Apakah kecocokan prefiks location nginx membedakan huruf besar dan kecil?
Di Linux, ya — location /Static/ tidak cocok dengan /static/x. Pada sistem berkas yang tidak membedakan huruf besar-kecil seperti macOS dan Cygwin, nginx membandingkan prefiks tanpa membedakannya dan sekaligus memaksa setiap location regex berperilaku seperti ~*. Halaman ini memodelkan perilaku Linux, yang hampir selalu dipakai server produksi. Kalau Anda mengembangkan di Mac dan merilis ke Linux, perbedaan itu bisa menyembunyikan aturan yang rusak sampai naik ke produksi.
Apakah try_files mengubah blok location mana yang terpilih?
Tidak. Pemilihan location selesai lebih dulu; try_files berjalan setelahnya, di dalam blok yang sudah menang. Jika sebuah permintaan tidak pernah sampai ke blok yang memuat try_files Anda, direktif itu tidak relevan — penyebab lazimnya adalah regex ~ \.php$ yang menyambar permintaan sebelum blok prefiks berisi fallback sempat bertindak. Redirect internal yang dikeluarkan belakangan memang memulai pencocokan dari awal, jadi URI yang sudah ditulis ulang diuji lagi terhadap daftar location dari atas.
Kenapa nginx membalas 301 saat saya meminta direktori tanpa garis miring?
Ada dua mekanisme berbeda yang menghasilkannya. Jika sebuah location yang namanya berakhiran / membawa proxy_pass atau direktif *_pass lain, permintaan ke path yang sama tanpa garis miring dijawab 301 saat pemilihan location — sebelum satu pun regex dievaluasi. Terpisah dari itu, modul berkas statis mengeluarkan 301 ketika path merujuk ke direktori nyata di disk. Yang pertama terlihat di sini; yang kedua bergantung pada sistem berkas Anda. Menambahkan location = /path menekan yang pertama.
Apakah blok location bersarang mengubah hasilnya?
Ya, dan dengan cara yang mudah terlewat. nginx turun ke dalam location prefiks pemenang lalu menelusuri anak-anaknya, sehingga regex bersarang diuji sebelum regex di level induk. Sebuah ^~ pada blok luar tidak melindunginya dari regex bersarang miliknya sendiri, dan penyarangan bisa membuat prefiks yang secara global lebih panjang jadi tidak terjangkau ketika saudara di level luar menang lebih dulu. Blok bersarang di sini dimodelkan dengan indentasi yang sama seperti yang Anda tulis.
Apakah konfigurasi nginx saya diunggah ke suatu tempat?
Tidak. Parsing dan pencocokan terjadi lokal di browser Anda dengan operasi string biasa — tidak ada panggilan ke server dan tidak ada yang disimpan. Hal ini lebih penting di sini daripada di kebanyakan alat, karena blok server sungguhan memuat hostname upstream, port internal, path sertifikat, dan aturan autentikasi. Anda tidak perlu percaya begitu saja: buka developer tools browser dan lihat panel Network tetap sunyi selagi Anda mengetik, atau putuskan koneksi sekalian dan lanjutkan menguji. Tidak adanya permintaan eksternal juga dijaga oleh uji kontrak otomatis pada setiap build, jadi hal itu tidak bisa berubah diam-diam.