Score:0

ใช้ส่วนหนึ่งของ URI เป็นหมายเลขพอร์ตสำหรับคำสั่ง nginx proxy_pass

ธง cn

นี่คือการกำหนดค่า nginx ของฉัน:

เซิร์ฟเวอร์ {
        ฟัง 443 ssl;
        server_name sub.example.fr ;
        ตำแหน่ง ~ ^/ (123[0-9])$ { # regex ทำงาน
                #rewrite ^/[0-9]{4}(.*)$ $1 สุดท้าย; # ไม่ทำงานด้วยสุดท้ายหรือทำลาย
                #proxy_pass http://localhost:$1/; # ไม่อนุญาตให้เพิ่มเครื่องหมายทับ
                proxy_pass http://localhost:$1;
        }
}

อยากส่งต่อ https://sub.example.fr/1234 ถึง http://localhost:1234ดังนั้นฉันต้องการแยกหมายเลขพอร์ต ลบออกจาก url และใช้ใน proxy_pass

Score:2
ธง gr

ก่อนอื่นของคุณ ^/(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;
}
themadmax avatar
cn flag
ขอบคุณมาก คำตอบของคุณน่าประทับใจและให้คำแนะนำดีมาก ฉันหวังว่ามันจะช่วยคนอื่นได้ !
Ivan Shatsky avatar
gr flag
ฉันได้ทำการอัปเดตคำตอบ (มีประโยชน์ ฉันหวังว่า) ใช่ คำตอบมีรายละเอียดค่อนข้างมาก (ไม่คุ้มที่จะลงคะแนนหรือไม่ :) ) ดังนั้น เพื่อช่วยให้ผู้อื่นพบข้อมูลนี้ คุณสามารถเปลี่ยนชื่อคำถามของคุณเป็นชื่ออื่นที่ใช้กันทั่วไป เช่น _ใช้ส่วนหนึ่งของ URI เป็น หมายเลขพอร์ตสำหรับ nginx proxy_pass directive_ หรือทั่วไปมากกว่านั้น _การใช้ส่วนหนึ่งของ URI ด้วย nginx proxy_pass directive_
us flag
เราสามารถจับภาพองค์ประกอบทั้งหมดในคำสั่ง 'สถานที่' และไม่ต้อง 'เขียนใหม่'

โพสต์คำตอบ

คนส่วนใหญ่ไม่เข้าใจว่าการถามคำถามมากมายจะปลดล็อกการเรียนรู้และปรับปรุงความสัมพันธ์ระหว่างบุคคล ตัวอย่างเช่น ในการศึกษาของ Alison แม้ว่าผู้คนจะจำได้อย่างแม่นยำว่ามีคำถามกี่ข้อที่ถูกถามในการสนทนา แต่พวกเขาไม่เข้าใจความเชื่อมโยงระหว่างคำถามและความชอบ จากการศึกษาทั้ง 4 เรื่องที่ผู้เข้าร่วมมีส่วนร่วมในการสนทนาด้วยตนเองหรืออ่านบันทึกการสนทนาของผู้อื่น ผู้คนมักไม่ตระหนักว่าการถามคำถามจะมีอิทธิพลหรือมีอิทธิพลต่อระดับมิตรภาพระหว่างผู้สนทนา