เข้าใจลำดับการจับคู่ Nginx Location ไม่ให้ Request วิ่งผิด Block
อธิบายความสำคัญของ exact match, prefix และ regular expression location พร้อมวิธีตรวจ config เมื่อหลาย block ซ้อนกันและ routing ไม่ทำงานตามที่คาด

ภาพรวม
หลายคนใช้ Nginx มานาน แต่ยังเคยงงว่าเขียน location หลายอันแล้วทำไมมันไม่วิ่งเข้า block ที่คิดไว้ 🤯
เบื้องหลังของ Nginx Location Matching มีลำดับการเลือกที่ค่อนข้างเป๊ะ และถ้าเข้าใจตรงนี้จะ debug config ได้ไวขึ้นมาก ⚙️
สิ่งที่น่าสนใจคือ Nginx ไม่ได้เลือก location ตามลำดับที่เขียนในไฟล์เสมอไป
มันมี “กติกาการจับคู่” ของตัวเอง และบางครั้ง regex ที่คิดว่าจะชนะ กลับแพ้ prefix ที่ใส่เครื่องหมายพิเศษไว้ 😵💫
หลักที่ควรรู้มีอยู่ 4 แบบ 🧩
location = /path ใช้จับคู่แบบเป๊ะทั้งเส้นทาง
location /path ใช้จับคู่แบบ prefix หรือขึ้นต้นด้วย path นี้
location ^~ /path ใช้จับคู่แบบ prefix เหมือนกัน แต่ถ้าแมตช์แล้ว Nginx จะไม่ไปเช็ก regex ต่อ 🚀
location ~ regex จับคู่ด้วย regex แบบแยกตัวพิมพ์เล็กใหญ่
location ~* regex จับคู่ด้วย regex แบบไม่แยกตัวพิมพ์เล็กใหญ่ 🔍
ลำดับการตัดสินใจโดยย่อมีแบบนี้
-
เช็ก exact match ก่อน ถ้าเจอ location = /something จะเลือกอันทันที ✅
-
เช็ก prefix match ที่ยาวที่สุด Nginx จะมองหา prefix ที่ตรงที่สุด ไม่ใช่อันที่เขียนก่อน
-
ถ้า prefix ที่ชนะมี ^~ เกมจบทันที ใช้อันนั้นเลย ไม่ไปดู regex 🔒
-
ถ้าไม่มี ^~ Nginx จะไล่เช็ก regex ตามลำดับที่เขียนจากบนลงล่าง อันแรกที่แมตช์จะชนะ 🎯
-
ถ้า regex ไม่แมตช์เลย กลับไปใช้ prefix ที่ยาวที่สุดที่หาไว้ก่อนหน้า
ตัวอย่างที่ทำให้หลายคนพลาดบ่อย 👇
location /images/ location ~* .(jpg|png|gif)$
ถ้า request เป็น /images/logo.png หลายคนคิดว่าจะเข้า /images/ แต่จริงๆ regex มีสิทธิ์ชนะ ถ้าไม่มี ^~ อยู่ที่ prefix 🧠
ถ้าเปลี่ยนเป็น location ^~ /images/ location ~* .(jpg|png|gif)$
แบบนี้ /images/logo.png จะเข้า block /images/ ทันที regex หมดสิทธิ์แทรก 🛑
อีกเคสที่เจอบ่อยในงาน API
location /api/ location /api/v1/ location ~ ^/api/.*/admin
ถ้าเรียก /api/v1/user/admin Nginx จะหา prefix ที่ยาวที่สุดก่อน ซึ่งก็คือ /api/v1/ แต่ถ้าไม่มี ^~ มันยังไปเช็ก regex ต่อ และ regex อาจชนะได้ ⚠️
แปลว่า prefix ที่ยาวที่สุด ไม่ได้แปลว่าจะถูกใช้เสมอ ถ้ายังเปิดทางให้ regex เข้ามาแข่ง
ทริคที่ช่วยลดบั๊กใน production 🧰
ใช้ = กับ path สำคัญ เช่น / หรือ /health ถ้าต้องการความชัดเจนสูง
ใช้ ^~ กับ static files หรือ path ที่ไม่อยากให้ regex มายุ่ง เช่น /assets/ /images/ /static/ 📦
ระวัง regex ที่กว้างเกินไป เพราะอาจแย่ง request จาก location ที่ตั้งใจไว้
ถ้ามีหลาย regex จำไว้ว่า Nginx ใช้อันแรกที่แมตช์ ไม่ได้เลือกอันที่ดูเฉพาะเจาะจงที่สุด ✍️
เวลางงว่า request เข้าบล็อกไหน ให้เปิด debug log หรือแยกทดสอบทีละ location จะเห็นพฤติกรรมชัดขึ้น 🔬
อีกจุดที่คนมักไม่รู้ การทำงานของ location เป็นเรื่องของ URI matching ไม่ใช่ filesystem matching โดยตรง
แปลว่า path ที่เห็นใน URL กับ path จริงบนดิสก์เป็นคนละขั้นตอนกัน 🗂️ หลังจากเลือก location ได้แล้ว ค่อยไปดูต่อว่าจะใช้ root, alias, rewrite หรือ proxy_pass ยังไง
ตัวอย่าง mental model สั้นๆ 🧠
เป๊ะมาก่อน ยาวสุดมาก่อน ถ้าใส่ ^~ ให้หยุดเลย ถ้าไม่หยุด ค่อยเปิดศึก regex
จำ 4 บรรทัดนี้ได้ เวลาอ่าน config คนอื่นจะไวขึ้นมาก ⏱️
เรื่องนี้เล็กมากในสายตาหลายคน แต่ในระบบจริงมันทำให้เกิดทั้ง 404 แปลกๆ, static file หลุดไปเข้า app server, หรือ cache ไม่ทำงานได้เลย 💥
เข้าใจ Location Matching ดีครั้งเดียว จะช่วยให้ config Nginx อ่านง่ายขึ้น ดูแลง่ายขึ้น และมั่นใจเวลาปรับ route หน้าเว็บหรือ API มากขึ้น 🌐
แนวทางนำไปใช้
- นำแนวคิดจากโพสต์นี้ไปทดลองกับงานจริงของคุณ
- แยกเป็นขั้นตอนเล็ก ๆ แล้วทำทีละส่วน
- บันทึกผลลัพธ์และสิ่งที่เรียนรู้เพื่อต่อยอด
สรุป
อธิบายความสำคัญของ exact match, prefix และ regular expression location พร้อมวิธีตรวจ config เมื่อหลาย block ซ้อนกันและ routing ไม่ทำงานตามที่คาด