nginx rewrite: last vs break vs return ต่างกันอย่างไร
ทดลองบน Ubuntu ให้เห็นว่า rewrite แบบ last กับ break ส่ง request ไปจบที่ location ไหน เมื่อไรได้ 301 หรือ 302 ทำไม last ในบาง location วนจนได้ 500 และวิธีเปิด rewrite_log ดูทุกขั้น
สรุปก่อน: rewrite last, break และ return ใน nginx ต่างกันอย่างไร
ใน nginx คำสั่ง rewrite ที่ใช้ flag last จะเปลี่ยน URI แล้วเริ่มหา location ใหม่ ส่วน flag break เปลี่ยน URI แล้วทำงานต่อใน location เดิม ส่วน return ไม่เปลี่ยน URI เลย มันหยุดการประมวลผลแล้วตอบ client ทันที URI คือส่วน path ของ request เช่น /old/hello ส่วน flag คือคำท้ายคำสั่ง rewrite ที่บอกว่าเปลี่ยน URI แล้วให้ทำอะไรต่อ
ความต่างนี้ดูเล็ก แต่มันตัดสินว่า request จะไปจบที่ block ไหน ถ้าเลือกผิด คุณอาจได้ไฟล์ผิดตัว หรือได้ error 500 จาก loop ที่ nginx.org เตือนไว้เอง ด้านล่างเราจะสร้าง lab เล็กๆ บน Ubuntu ให้แต่ละ location ตอบด้วยชื่อของตัวเอง แล้วให้ curl บอกว่า block ไหนเป็นคนตอบจริง
ความหมายของแต่ละตัวตามคำของ nginx.org (หน้า ngx_http_rewrite_module อ่านเมื่อ 13 ตุลาคม 2026) มีดังนี้:
lastหยุดชุดคำสั่งของ rewrite module ที่กำลังทำอยู่ แล้ว "starts a search for a new location matching the changed URI" คือเริ่มหา location ใหม่ที่ตรงกับ URI ที่เปลี่ยนแล้วbreakหยุดชุดคำสั่งของ rewrite module เหมือนคำสั่งbreakและถ้าอยู่ใน location ก็ประมวลผล request ต่อใน location นั้นredirectตอบ client เป็น redirect ชั่วคราวด้วย code 302permanentตอบ client เป็น redirect ถาวรด้วย code 301returnหยุดการประมวลผลแล้วส่ง code ที่กำหนดกลับไปให้ client
rewrite ทำอะไรกับ request กันแน่
รูปแบบคำสั่งคือ rewrite regex replacement [flag]; ใช้ได้ใน context server, location และ if ส่วน regex (regular expression) คือรูปแบบข้อความที่ใช้จับคู่ ถ้า regex ตรงกับ URI ของ request nginx จะเปลี่ยน URI ตามที่ replacement บอก
เอกสารของ nginx.org วางกฎไว้สี่ข้อ ข้อแรก คำสั่ง rewrite ทำงานเรียงตามลำดับที่เขียนในไฟล์ config ข้อสอง flag หยุดการประมวลผลคำสั่งที่เหลือได้ ข้อสาม ถ้า replacement ขึ้นต้นด้วย http://, https:// หรือ $scheme การประมวลผลจะหยุด และ nginx ส่ง redirect กลับไปให้ client ข้อสี่ ถ้า replacement มี argument ใหม่ (query string หลังเครื่องหมาย ?) argument เดิมจะถูกต่อท้าย argument ใหม่
จุดที่คนพลาดบ่อยที่สุดคือคำว่า "ชุดคำสั่งของ rewrite module" ชุดนี้ไม่ได้มีแค่ rewrite แต่ยังมี return, if, set และ break ด้วย เพราะทั้งหมดอยู่ในโมดูลเดียวกัน แปลว่าหลัง rewrite ... last หรือ rewrite ... break ที่ regex ตรงแล้ว บรรทัด return ที่เขียนต่อในบล็อกเดียวกันจะไม่ทำงาน lab ด้านล่างใส่ return แบบนี้ไว้โดยตั้งใจ เพื่อให้คุณเห็นว่ามันไม่ทำงานจริง
ทำไม last ต้องหา location ใหม่: ทบทวนลำดับการจับคู่ location
last ไม่ได้กระโดดไปที่ location ใดโดยตรง มันส่ง URI ใหม่กลับไปให้ nginx เลือก location อีกรอบด้วยกฎเดิม ตามเอกสาร ngx_http_core_module กฎนั้นคือ:
- nginx ตรวจ location แบบ prefix ก่อน แล้วจำตัวที่ prefix ยาวที่สุดที่ตรงไว้
- location แบบ
=เป็นการจับคู่ตรงตัว ถ้าตรง การค้นหาจบทันที - ถ้า prefix ที่ยาวที่สุดมี
^~nginx จะไม่ตรวจ regex - จากนั้น nginx ตรวจ location แบบ regex ตามลำดับในไฟล์ ตัวแรกที่ตรงคือตัวที่ถูกใช้
- ถ้าไม่มี regex ไหนตรง nginx ใช้ prefix ที่จำไว้
เพราะ last วิ่งผ่านกฎนี้ใหม่ทั้งหมด URI ใหม่จึงอาจไปตกที่ location ที่คุณไม่ได้คาด หรือตกกลับมาที่ location เดิม กรณีหลังคือที่มาของ loop ที่จะเห็นในหัวข้อต่อๆ ไป
เตรียม lab บน Ubuntu: nginx จาก apt และ server block บน port 8080
ใช้ VPS หรือ VM ที่ทิ้งได้ lab นี้ใช้ Ubuntu 24.04 และ nginx จาก apt ทุกคำสั่ง curl ยิงจากตัวเครื่องเองไปที่ 127.0.0.1 คุณจึงไม่ต้องเปิด firewall เพิ่ม
sudo apt update
sudo apt install -y nginx curl
sudo systemctl enable --now nginx
nginx -vnginx -v บอก version ที่คุณกำลังทดสอบ ณ วันที่ 13 ตุลาคม 2026 หน้า packages.ubuntu.com แสดง package nginx ของ Ubuntu 24.04 เป็น 1.24.0-2ubuntu7.18 และของ Ubuntu 26.04 เป็น 1.28.3-2ubuntu1.11 ตัวเลขนี้เปลี่ยนตาม security update เอกสารของ flag ทั้งสี่ ขีดจำกัด 10 รอบ และ rewrite_log ไม่มีหมายเหตุเรื่อง version สำหรับรุ่นเหล่านี้ แต่ Ubuntu อาจ patch ต่างจาก upstream ได้ ผลที่เครื่องคุณจึงเป็นตัวตัดสิน
สร้างไฟล์หนึ่งไฟล์ไว้ให้ตัวอย่าง break เสิร์ฟ:
sudo install -d -m 755 /srv/rewrite-lab/new
echo "file /srv/rewrite-lab/new/hello" | sudo tee /srv/rewrite-lab/new/hello > /dev/nullแล้วเขียน server block ของ lab ทุก location ตอบด้วย return 200 พร้อมชื่อของตัวเอง curl จึงบอกได้ทันทีว่า block ไหนเป็นคนตอบ
sudo tee /etc/nginx/conf.d/rewrite-lab.conf > /dev/null <<'EOF'
server {
listen 8080;
error_log /var/log/nginx/rewrite-lab.error.log notice;
rewrite_log on;
location / {
return 200 "location /\n";
}
location /new/ {
return 200 "location /new/ uri=$uri args=$args\n";
}
location /old/ {
rewrite ^/old/(.*)$ /new/$1 last;
return 200 "location /old/\n";
}
location /brk/ {
root /srv/rewrite-lab;
rewrite ^/brk/(.*)$ /new/$1 break;
return 200 "location /brk/\n";
}
location /temp/ {
rewrite ^/temp/(.*)$ /new/$1 redirect;
}
location /perm/ {
rewrite ^/perm/(.*)$ /new/$1 permanent;
}
location /ext/ {
rewrite ^/ext/(.*)$ https://example.com/$1;
}
location /args/ {
rewrite ^/args/(.*)$ /new/?user=$1 last;
}
location /args-clean/ {
rewrite ^/args-clean/(.*)$ /new/?user=$1? last;
}
location /loop/ {
rewrite ^/loop/(.*)$ /loop/x$1 last;
}
location = /old-page {
return 301 /new/page;
}
}
EOFตรวจ syntax แล้ว reload:
sudo nginx -t
sudo systemctl reload nginx
sudo nginx -T 2>/dev/null | grep -n 'rewrite-lab.conf'
curl -s http://127.0.0.1:8080/nginx -t ต้องรายงานว่า syntax ผ่านและ test สำเร็จ ถ้าไม่ผ่าน มันจะบอกชื่อไฟล์และเลขบรรทัดที่ผิด คำสั่ง nginx -T พิมพ์ config ทั้งหมดที่ nginx โหลดจริง บรรทัดที่ grep เจอต้องมีชื่อ rewrite-lab.conf ถ้าไม่เจอเลย แปลว่า nginx.conf บนเครื่องคุณไม่ได้ include โฟลเดอร์ conf.d ให้ตรวจด้วย grep -n include /etc/nginx/nginx.conf สุดท้าย curl ควรพิมพ์ location / ออกมา
last: เปลี่ยน URI แล้วเริ่มหา location ใหม่
curl -s http://127.0.0.1:8080/old/helloคุณควรเห็นบรรทัดที่ขึ้นต้นด้วย location /new/ และมี uri=/new/hello ไม่ใช่ location /old/ ลำดับเหตุการณ์เป็นแบบนี้ regex ใน /old/ ตรง URI จึงกลายเป็น /new/hello จากนั้น last หยุดชุดคำสั่งของ rewrite module ใน /old/ บรรทัด return ในบล็อกนั้นจึงไม่ได้ทำงาน แล้ว nginx หา location ใหม่ด้วย URI /new/hello prefix ที่ยาวที่สุดที่ตรงคือ /new/ บล็อกนั้นจึงเป็นคนตอบ
break: เปลี่ยน URI แต่อยู่ใน location เดิม
curl -s http://127.0.0.1:8080/brk/helloคราวนี้คุณควรเห็น file /srv/rewrite-lab/new/hello ซึ่งเป็นเนื้อไฟล์ที่สร้างไว้ ไม่ใช่ location /new/ และไม่ใช่ location /brk/ เหตุผลมีสองชั้น ชั้นแรก break หยุดชุดคำสั่งของ rewrite module บรรทัด return ใน /brk/ จึงไม่ทำงาน เหมือนกรณี last ชั้นที่สอง break ไม่เริ่มการหา location ใหม่ request จึงอยู่ใน /brk/ ต่อ บล็อกนี้ไม่มีคำสั่งตอบเหลือแล้ว nginx จึงเสิร์ฟไฟล์ static ตาม root ของบล็อกนี้ โดยใช้ URI ที่เปลี่ยนแล้ว คือ /srv/rewrite-lab ต่อด้วย /new/hello
ลองขอไฟล์ที่ไม่มีอยู่:
curl -si http://127.0.0.1:8080/brk/missingดูบรรทัดแรกของ output ว่า nginx ตอบ status อะไรบนเครื่องคุณ จุดสำคัญคือ body ไม่ใช่ location /new/ แม้ URI จะกลายเป็น /new/missing แล้ว เพราะ break ไม่หา location ใหม่ nginx จึงหาไฟล์ /srv/rewrite-lab/new/missing แทน
ตรรกะเดียวกันใช้กับ location ที่จบด้วย proxy_pass ด้วย break ทำให้ request อยู่ในบล็อกที่มี proxy_pass ต่อ ส่วน last ส่ง request ไปหา location อื่น ถ้าคุณกำลังไล่ config แบบนั้น อ่าน คำอธิบาย config reverse proxy ของ nginx ประกอบ
redirect และ permanent: เมื่อไรที่ client เห็น 302 หรือ 301
สอง flag นี้ไม่หา location ใหม่ภายใน server มันส่ง redirect กลับไปให้ client แล้วให้ client ขอ URL ใหม่เอง ใช้ curl -si เพื่อดู header ด้วย
curl -si http://127.0.0.1:8080/temp/hello
curl -si http://127.0.0.1:8080/perm/hellonginx.org บอกว่า redirect ตอบด้วย code 302 และ permanent ตอบด้วย code 301 ดูบรรทัดแรกของแต่ละ output ว่าเครื่องคุณตอบตามนั้นหรือไม่ แล้วดู header Location ว่า nginx ส่ง URL อะไรออกไป
อย่าเดา header Location ล่วงหน้า เอกสารบอกว่า URL เต็มของ redirect สร้างจาก scheme ของ request ($scheme) ร่วมกับคำสั่ง server_name_in_redirect และ port_in_redirect สองคำสั่งนี้ตัดสินว่า host ใน Location มาจากไหน และ port 8080 จะติดไปด้วยหรือไม่ ถ้า URL ที่ได้มี host หรือ port ผิด สองคำสั่งนี้คือที่แรกที่ต้องดู
curl ไม่ตาม redirect เองถ้าไม่ใส่ -L คุณจึงเห็นคำตอบแรกของ nginx ตรงๆ ซึ่งคือสิ่งที่ต้องการเมื่อ debug
replacement ที่ขึ้นต้นด้วย https:// กลายเป็น redirect ทันที
curl -si http://127.0.0.1:8080/ext/helloบรรทัด rewrite ใน /ext/ ไม่มี flag แต่ replacement ขึ้นต้นด้วย https:// เอกสารบอกว่ากรณีนี้การประมวลผลหยุด และ redirect ถูกส่งกลับไปให้ client ใน source code ของ ngx_http_rewrite_module.c กรณีนี้นับเป็น redirect แบบ 302 แม้ไม่ใส่ flag ดู status และ Location ที่เครื่องคุณตอบ แล้วเทียบกับผลของ /temp/
ด้วยเหตุนี้เอกสารจึงบอกให้ใช้ flag redirect เฉพาะเมื่อ replacement ไม่ได้ขึ้นต้นด้วย http://, https:// หรือ $scheme ถ้าต้องการ 301 ไปยังโดเมนอื่น ให้ใส่ permanent ท้ายบรรทัด
query string: ทำไม argument เดิมถูกต่อท้าย และ ? ตัวท้ายทำอะไร
curl -s 'http://127.0.0.1:8080/args/alice?ref=mail'
curl -s 'http://127.0.0.1:8080/args-clean/bob?ref=mail'ทั้งสองคำสั่งไปจบที่ /new/ เพราะใช้ last ให้ดูค่าหลัง args= ในบรรทัดที่ได้ บรรทัดแรกควรมี user=alice และมี ref=mail ต่อท้าย เพราะเอกสารบอกว่าถ้า replacement มี argument ใหม่ argument เดิมจะถูกต่อท้าย บรรทัดที่สองควรมีแค่ user=bob เพราะเครื่องหมาย ? ตัวสุดท้ายใน replacement ปิดการต่อท้ายนั้น เอกสารเองก็ใช้ตัวอย่างแบบเดียวกัน คือ rewrite ^/users/(.*)$ /show?user=$1? last;
กับดักที่ nginx.org เตือนเอง: rewrite ... last ใน location ที่ URI ใหม่วนกลับมา
เอกสาร ngx_http_rewrite_module มีตัวอย่าง rewrite แบบ last ที่วางไว้ใน server context แล้วเตือนว่า ถ้าย้ายคำสั่งเหล่านี้เข้าไปใน location /download/ ต้องเปลี่ยน last เป็น break "otherwise nginx will make 10 cycles and return the 500 error" คือถ้าไม่เปลี่ยน nginx จะวน 10 รอบแล้วตอบ error 500
กลไกคือสิ่งที่เห็นในหัวข้อ last แล้ว last หา location ใหม่ ถ้า URI ใหม่ตกกลับมาที่ location เดิม และ regex ยังตรงอยู่ rewrite ก็ทำงานอีกรอบ แล้วส่งไปหา location ใหม่อีกครั้ง บล็อก /loop/ ใน lab สร้างกรณีที่แย่ที่สุดไว้ /loop/a กลายเป็น /loop/xa ซึ่งยังขึ้นต้นด้วย /loop/ และยังตรง regex เดิม ทุกรอบจึงเติม x อีกหนึ่งตัว และ rewrite เองไม่มีวันหยุด
curl -si http://127.0.0.1:8080/loop/a
sudo tail -n 20 /var/log/nginx/rewrite-lab.error.logดูบรรทัดแรกของ output จาก curl ว่า nginx ตอบ status อะไร แล้วดูท้าย error log สิ่งที่หยุด loop คือค่าคงที่ NGX_HTTP_MAX_URI_CHANGES ซึ่งไฟล์ ngx_http_request.h ใน source code ของ nginx กำหนดไว้เป็น 10 เมื่อตัวนับหมด โค้ดใน ngx_http_core_module.c เขียน log ที่ระดับ error แล้วจบ request ด้วย 500 ข้อความนี้อยู่ในระดับ error จึงขึ้นใน log แม้คุณไม่ได้ตั้ง notice ไว้ ให้หาบรรทัดที่มีคำว่า cycle และ URI ที่กำลังประมวลผล ส่วนบรรทัดระดับ notice ที่อยู่ก่อนหน้าคือผลจาก rewrite_log ซึ่งแสดงแต่ละรอบ นับจำนวนรอบเองจาก log ของคุณ อย่าเชื่อตัวเลขจากที่อื่นโดยไม่ตรวจ
nginx -t ไม่จับปัญหานี้ เพราะทุกบรรทัดถูก syntax loop เกิดตอนมี request เข้ามาเท่านั้น วิธีเดียวที่จะเห็นมันก่อนผู้ใช้คือยิง request ทดสอบแบบที่ทำอยู่นี้
แก้ loop ของ rewrite last อย่างไร
- เปลี่ยน
lastเป็นbreakตามที่ nginx.org แนะนำ request จะอยู่ใน location เดิมและไม่วนกลับไปหา location ใหม่ แต่หลังbreakบล็อกนั้นต้องมีสิ่งที่ตอบ request ได้ เช่นrootหรือproxy_passเหมือนตัวอย่าง/brk/ - ถ้าคุณต้องการ
lastจริงๆ ให้เขียน regex ที่ไม่ตรงกับ URI ใหม่ หรือให้ URI ใหม่ไปตกที่ location อื่น ตัวอย่างในเอกสารเองวางrewrite ... lastไว้ใน server context ไม่ใช่ใน location ที่ rewrite เข้าไปหา
หลังแก้ ให้รัน sudo nginx -t และ sudo systemctl reload nginx แล้วยิง curl -si ซ้ำ บรรทัดที่มีคำว่า cycle ไม่ควรเพิ่มขึ้นใน log อีก
เปิด rewrite_log เพื่อดูการตัดสินใจของ rewrite ทีละขั้น
rewrite_log ปิดอยู่เป็นค่าเริ่มต้น ใช้ได้ใน context http, server, location และ if เมื่อเปิด nginx จะเขียนผลการทำงานของคำสั่งใน rewrite module ลง error_log ที่ระดับ notice
ตรงนี้คือจุดที่คนเปิดแล้วไม่เห็นอะไร ตามเอกสาร ngx_core_module ระดับ log เรียงจากเบาไปหนักคือ debug, info, notice, warn, error, crit, alert, emerg การตั้งระดับหนึ่งจะเก็บระดับนั้นและระดับที่หนักกว่า ระดับเริ่มต้นคือ error ซึ่งเก็บแค่ error, crit, alert และ emerg ข้อความระดับ notice จึงถูกทิ้ง ถ้าคุณเปิดแค่ rewrite_log on; โดยไม่ลดระดับของ error_log คุณจะไม่เห็นอะไรเลย
นี่คือเหตุผลที่ lab ตั้งสองบรรทัดนี้ไว้ใน server block ตรงๆ:
error_log /var/log/nginx/rewrite-lab.error.log notice;
rewrite_log on;เราไม่พึ่งค่าใน nginx.conf ของ package เพราะ path และระดับในไฟล์นั้นอาจต่างกันไปในแต่ละเครื่อง ตั้งไว้เองใน server block ที่ทดสอบจะแน่นอนกว่า ลองดูการตัดสินใจของ last อีกครั้ง:
curl -s http://127.0.0.1:8080/old/hello
sudo tail -n 5 /var/log/nginx/rewrite-lab.error.logบรรทัดใหม่ควรอยู่ในระดับ notice ตาม source code ใน ngx_http_script.c ข้อความเหล่านี้บอกว่า regex ตรงกับ URI หรือไม่ และ URI หลัง rewrite เป็นอะไร เมื่อเป็น redirect มันบอก URL ที่ส่งกลับไปด้วย อ่านข้อความจริงจาก log ของคุณ แล้วเทียบกับลำดับเหตุการณ์ในหัวข้อ last และ break
บน server ที่มี traffic จริง ให้ปิด rewrite_log และคืน error_log เป็นระดับเดิมเมื่อ debug เสร็จ เพราะทุก request ที่ผ่าน rewrite จะเขียน log อย่างน้อยหนึ่งบรรทัด
เมื่อไรไม่ควรใช้ rewrite
rewrite เหมาะเมื่อคุณต้องใช้ regex จับส่วนของ URI แล้วสร้าง URI ใหม่ งานอีกหลายแบบมีคำสั่งที่ตรงกว่า
redirect ที่ปลายทางตายตัว ใช้ return 301 ถ้าหน้าเก่าหนึ่งหน้าย้ายไปที่ใหม่หนึ่งหน้า ไม่ต้องใช้ regex เลย lab มีตัวอย่างนี้อยู่แล้ว:
location = /old-page {
return 301 /new/page;
}curl -si http://127.0.0.1:8080/old-pageดู status และ Location ที่เครื่องคุณตอบ return หยุดการประมวลผลแล้วส่ง code กลับทันที สำหรับ code 301, 302, 303, 307 และ 308 อาร์กิวเมนต์ตัวที่สองคือ URL ปลายทาง ถ้าให้เป็น URI ภายใน server เดียวกันแบบนี้ nginx สร้าง URL เต็มจาก $scheme, server_name_in_redirect และ port_in_redirect เหมือนกรณี rewrite ส่วน location แบบ = จบการค้นหา location ทันที nginx จึงไม่ต้องรัน regex ใดๆ คนที่อ่าน config ต่อจากคุณก็เห็นเจตนาได้ในบรรทัดเดียว
ตรวจว่าไฟล์มีอยู่ไหม แล้วค่อย fallback ใช้ try_files คำสั่ง try_files ตรวจไฟล์ตามลำดับและใช้ตัวแรกที่เจอ ถ้าไม่เจอเลยจะทำ internal redirect ไปยัง URI ที่เป็นพารามิเตอร์ตัวสุดท้าย งานแบบนี้ไม่ต้องเขียน regex ด้วย rewrite
redirect ไป www หรือไป HTTPS เป็นเรื่องของ canonical URL ซึ่งอยู่นอกเรื่องของ lab นี้ ถ้ากำลังตัดสินใจเรื่องนี้ อ่าน ความต่างระหว่าง HTTP กับ HTTPS บน server ของคุณ ก่อน แล้วค่อย ติดตั้งใบรับรอง Let's Encrypt ให้ nginx ด้วย certbot บน Ubuntu 24.04
ล้าง lab
sudo rm /etc/nginx/conf.d/rewrite-lab.conf
sudo rm -r /srv/rewrite-lab
sudo nginx -t
sudo systemctl reload nginx
sudo rm /var/log/nginx/rewrite-lab.error.logหลัง reload แล้ว ไม่มีอะไรฟังที่ port 8080 อีก curl -s http://127.0.0.1:8080/ จึงควรเชื่อมต่อไม่ได้ ส่วน site อื่นบนเครื่องยังทำงานตามเดิม เพราะเราลบแค่ไฟล์ของ lab
FAQ
rewrite last กับ break ใน nginx ต่างกันอย่างไร
ทั้งสองเปลี่ยน URI และหยุดชุดคำสั่งของ rewrite module ที่เหลือในบล็อกนั้น รวมถึง return ที่เขียนต่อท้าย ต่างกันที่ขั้นถัดไป last เริ่มหา location ใหม่ด้วย URI ที่เปลี่ยนแล้ว ส่วน break ประมวลผล request ต่อใน location เดิม วิธีทดสอบที่ง่ายที่สุดคือให้แต่ละ location ตอบ return 200 พร้อมชื่อของตัวเอง แล้วดูว่า curl ได้อะไรกลับมา
ทำไม rewrite ... last ทำให้ nginx ตอบ 500
เมื่อ rewrite ... last อยู่ใน location ที่ URI ใหม่ตกกลับมาหา และ regex ยังตรง nginx จะ rewrite แล้วหา location ซ้ำไปเรื่อยๆ เอกสาร nginx.org เตือนว่ากรณีนี้ nginx "will make 10 cycles and return the 500 error" ขีดจำกัดนี้คือค่าคงที่ NGX_HTTP_MAX_URI_CHANGES ใน source code แก้โดยเปลี่ยน last เป็น break หรือเขียน regex ให้ไม่ตรงกับ URI ใหม่ แล้วยืนยันด้วย curl -si และ error log
เปิด rewrite_log on แล้วทำไมไม่เห็นอะไรใน log
rewrite_log เขียนข้อความที่ระดับ notice แต่ระดับเริ่มต้นของ error_log คือ error ซึ่งไม่รวม notice ข้อความจึงถูกทิ้ง ให้ตั้ง error_log ของ server ที่กำลัง debug เป็นระดับ notice เช่น error_log /var/log/nginx/rewrite-lab.error.log notice; แล้ว reload nginx
redirect หน้าเดียวควรใช้ return 301 หรือ rewrite permanent
ถ้าปลายทางตายตัว ใช้ return 301 ใน location แบบ = มันไม่ต้องใช้ regex และหยุดการประมวลผลทันที rewrite ... permanent เหมาะเมื่อคุณต้องจับส่วนของ URI ด้วย regex แล้วใส่ลงใน URL ปลายทาง เอกสารบอกว่าทั้งสองแบบให้ code 301 แต่ควรดู status และ Location จริงด้วย curl -si ทุกครั้ง
ทำไม header Location ของ redirect มี host หรือ port ไม่ตรงกับที่คาด
เมื่อ redirect ชี้ไปที่ URI ภายใน server nginx สร้าง URL เต็มจาก scheme ของ request ร่วมกับคำสั่ง server_name_in_redirect และ port_in_redirect ถ้า Location มี port ทดสอบติดมา หรือมีชื่อ host ผิด ให้ตรวจสองคำสั่งนี้ใน server block แล้วยิง curl -si ใหม่หลัง reload