ก่อนอื่นของคุณ ^/(123[0-9])$
regex จะจับคู่เท่านั้น /1234
URI (หรือ /1230
, /1231
ฯลฯ) แต่ไม่ใช่การ /1234/some/path
เนื่องจากคุณใช้ $
สมอปลายสาย ฉันถือว่ามันไม่ใช่ข้อผิดพลาด แต่เป็นโซลูชันการออกแบบ ถ้าไม่ใช่ ให้จับคู่ทั้งสองอย่าง /1234
และ /1234/some/path
(แต่ไม่เหมือน. /12345
) คุณสามารถใช้การสลับ: ^/(123[0-9])(?:/|$)
(ฉันใช้กลุ่มที่ไม่ใช่การจับภาพ (?:...)
เนื่องจากถือว่ามีประสิทธิภาพดีกว่าแคปเจอร์กรุ๊ปเล็กน้อย)
การกำหนดค่าของคุณมีข้อผิดพลาดมากมาย มาดูกันดีกว่า
ข้อผิดพลาด # 1: ไม่ถูกต้อง เขียนใหม่ ... สุดท้าย;
การใช้งาน
แน่นอน คุณไม่สามารถระบุ URI สำหรับ proxy_pass
ต้นน้ำเหมือนกับที่คุณพยายามทำโดยใช้เครื่องหมายทับ
proxy_pass http://localhost:$1/; # ไม่อนุญาตให้เพิ่มเครื่องหมายทับ
ภายในตำแหน่งที่ตรงกันของ regex (รวมถึงภายในตำแหน่งที่ตั้งที่มีชื่อ) และวิธีเดียวที่จะเปลี่ยน URI ที่จะถูกส่งผ่านไปยังแบ็กเอนด์คือการใช้ เขียนใหม่
คำสั่ง อย่างไรก็ตาม วิธีที่ถูกต้องในการเปลี่ยน URI ภายในไฟล์ ที่ตั้ง
บล็อกเพื่อดำเนินการในภายหลังภายในตำแหน่งเดียวกันที่จะใช้ เขียนใหม่ ... ทำลาย;
เนื่องจาก เขียนใหม่ ... สุดท้าย;
จะบังคับให้ nginx ค้นหาตำแหน่งใหม่สำหรับ URI ที่เขียนใหม่ นั่นหมายความว่าเราต้องใช้ หยุดพัก
ธงสำหรับ เขียนใหม่
คำสั่ง:
เขียนใหม่ ^/[0-9]{4}(.*)$ $1 ตัวแตก;
ระวัง! ไม่มีคำสั่งจาก ngx_http_rewrite_module
จะถูกดำเนินการหลังจากนั้น เขียนใหม่ ... ทำลาย;
(หรือเรียกง่ายๆว่า หยุดพัก;
) คำสั่ง (อัปเดต: หลังจากการทดสอบบางอย่างตรงข้ามกับที่กล่าวไว้ใน เอกสารปรากฎว่าเป็นจริงสำหรับ หยุดพัก
คำสั่ง แต่ไม่ใช่ เขียนใหม่ ... ทำลาย
หนึ่งอย่างน้อยสำหรับ OpenResty 1.17.8.2 ที่ใช้ nginx 17.8 core)
ข้อผิดพลาด #2: คุณควรอ้างอิงสตริงใดๆ ที่มีวงเล็บปีกกา มิฉะนั้นจะถูกพิจารณาว่าเป็นบล็อกการกำหนดค่า nginx
คำสั่งก่อนหน้าจะทำให้เรามีข้อผิดพลาดดังต่อไปนี้:
nginx: [emerg] คำสั่ง "เขียนใหม่" ไม่ได้สิ้นสุดโดย ";"
เพื่อกำจัดข้อผิดพลาดนี้ เราจำเป็นต้องอ้างอิงรูปแบบ regex เนื่องจากการใช้วงเล็บปีกกา:
เขียนใหม่ "^/[0-9]{4}(.*)$" $1 ตัวแบ่ง;
ความผิดพลาด #3: การจับภาพที่เป็นตัวเลขจะถูกเขียนทับทุกครั้งที่มีการประเมินนิพจน์ทั่วไป
สมมติว่าคุณมี URI เป็น /1234
:
ตำแหน่ง ~ ^/(123[0-9])$ {
# ที่นี่ค่าของตัวแปร '$1' คือ "1234"
เขียนใหม่ "^/[0-9]{4}(.*)$" $1 ตัวแบ่ง;
# ที่นี่ค่าของตัวแปร '$1' เป็นสตริงว่าง!
proxy_pass http://localhost:$1; # จะไม่มีพอร์ตสำหรับคำสั่ง 'proxy_pass'
}
คุณสามารถบันทึกได้ $1
ค่าก่อนที่กฎการเขียนใหม่จะประเมินนิพจน์ทั่วไปของตัวเองโดยใช้ ชุด
คำสั่ง:
ตำแหน่ง ~ ^/(123[0-9])$ {
ตั้ง $พอร์ต $1;
เขียนใหม่ "^/[0-9]{4}(.*)$" $1 ตัวแบ่ง;
proxy_pass http://localhost:$port;
}
หรือดีกว่าใช้ ชื่อกลุ่มจับภาพ:
ตำแหน่ง ~ ^/(?<พอร์ต>123[0-9])$ {
เขียนใหม่ "^/[0-9]{4}(.*)$" $1 ตัวแบ่ง;
proxy_pass http://localhost:$port;
}
บางครั้งไม่มีวิธีแก้ปัญหาอื่นนอกจากใช้การจับภาพที่มีชื่อ ตัวอย่างที่ดีของสถานการณ์ดังกล่าวมีให้ที่ นี้ เกลียว.
ข้อผิดพลาด #4: URI ที่เขียนใหม่ต้องไม่เป็นสตริงว่าง
สมมติว่าคุณมี URI เป็น /1234
. หลังจากเขียนกฎใหม่แล้ว nginx ภายใน $ยูริ
ตัวแปรจะมีค่าว่าง ซึ่งจะนำไปสู่ข้อผิดพลาด HTTP 500 Internal Server และในบันทึกข้อผิดพลาด nginx คุณจะเห็นข้อความแสดงข้อผิดพลาดต่อไปนี้:
URI ที่เขียนใหม่มีความยาวเป็นศูนย์
หากต้องการแก้ไขข้อผิดพลาดนั้น ให้เขียน URI ใดๆ ใหม่ลงใน /
:
ตำแหน่ง ~ ^/(?<พอร์ต>123[0-9])$ {
เขียนใหม่ ^ / แบ่ง;
proxy_pass http://localhost:$port;
}
หากคุณต้องการให้บริการใดๆ /<พอร์ต_number>/บาง/เส้นทาง
คำขอข้างต้น คุณควรใช้บล็อกตำแหน่งต่อไปนี้เพื่อให้แน่ใจว่า URI ที่เขียนใหม่ของคุณเริ่มต้นด้วยเครื่องหมายทับ:
ตำแหน่ง ~ ^/(?<พอร์ต>123[0-9])(?:/|$) {
เขียนใหม่ "^/\d{4}(?:/(.*))" /$1 พัก;
proxy_pass http://localhost:$port;
}
ข้อผิดพลาด #5: คุณต้องระบุตัวแก้ไขเมื่อใช้ตัวแปรกับ proxy_pass
คำสั่ง
การกำหนดค่าข้างต้นใกล้เคียงกับโซลูชันการทำงาน อย่างไรก็ตาม มันยังใช้งานไม่ได้ ทำให้คุณได้รับข้อผิดพลาด HTTP 502 Bad Gateway คุณต้องระบุ ตัวแก้ไข
เมื่อคุณใช้ตัวแปรกับ proxy_pass
directive และอัปสตรีมของคุณถูกระบุด้วยชื่อโดเมนแทนที่จะเป็นที่อยู่ IP มิฉะนั้น คุณจะได้รับข้อผิดพลาดต่อไปนี้ในบันทึกข้อผิดพลาด nginx ของคุณ:
ไม่มีตัวแก้ไขที่กำหนดเพื่อแก้ไข localhost
โดยทั่วไปคุณจะต้องใช้บางอย่างเช่น
ตัวแก้ไข 8.8.8.8;
ตำแหน่ง ~ ^/(?<พอร์ต>123[0-9])$ {
เขียนใหม่ ^ / แบ่ง;
proxy_pass http://localhost:$port;
}
แต่เนื่องจากต้นน้ำของคุณคือ โลคัลโฮสต์
คุณสามารถระบุที่อยู่ IP แทนชื่อโดเมนได้ วิธีนี้คุณไม่จำเป็นต้องใช้ ตัวแก้ไข
คำสั่งเลย:
ตำแหน่ง ~ ^/(?<พอร์ต>123[0-9])$ {
เขียนใหม่ ^ / แบ่ง;
proxy_pass http://127.0.0.1:$port;
}
การกำหนดค่านี้ควรใช้งานได้อย่างสมบูรณ์ (ในที่สุด) และอีกครั้งหากคุณต้องการให้บริการใด ๆ /<พอร์ต_number>/บาง/เส้นทาง
คำขอข้างต้น คุณควรใช้บล็อกตำแหน่งต่อไปนี้แทน:
ตำแหน่ง ~ ^/(?<พอร์ต>123[0-9])(?:/|$) {
เขียนใหม่ "^/\d{4}(?:/(.*))" /$1 พัก;
proxy_pass http://127.0.0.1:$port;
}