การเขียน url ใหม่ของ nginx: ความแตกต่างระหว่างตัวแบ่งและตัวสุดท้าย


45

ฉันไม่เข้าใจความแตกต่างระหว่างการหยุดพักและครั้งสุดท้าย (ตั้งค่าสถานะการเขียนใหม่) เอกสารค่อนข้างลึกซึ้ง ฉันพยายามสลับระหว่างสองอย่างในการกำหนดค่าบางอย่างของฉัน แต่ฉันไม่เห็นความแตกต่างของพฤติกรรม ใครช่วยอธิบายธงเหล่านี้ให้ละเอียดหน่อยได้ไหม? มีตัวอย่างที่แสดงพฤติกรรมที่แตกต่างกันโดยเฉพาะอย่างยิ่งเมื่อพลิกธงหนึ่งไปยังอีก


ฉันไม่ทราบคำตอบ แต่โปรดอัปเดต wiki.nginx.org เมื่อคุณได้รับคำตอบ นอกจากนี้รายชื่อผู้รับจดหมาย nginx ภาษาอังกฤษนั้นค่อนข้างใช้งานได้และ Igor (ผู้พัฒนาหลัก) จะตอบคำถามหลายร้อยคำถามต่อเดือนดังนั้นอาจถามที่นั่น
rmalayter

@rmalayter - คำถามนี้ถูกถามในรายชื่อผู้รับจดหมายของ nginx อิกอร์ตอบ แต่คำตอบก็ไม่สมเหตุสมผลสำหรับฉันเช่นกัน: pubbs.net/nginx/200908/46047

การเชื่อมโยง pubbs.net เสียเนื่องจากโดเมนถูกยึดครอง ขออภัยไม่สามารถหาตำแหน่งที่ควรจะชี้ได้ ; (
Tino

คำตอบ:


40

คุณอาจมีกฎการเขียนซ้ำที่แตกต่างกันสำหรับสถานที่ต่างกัน เมื่อโมดูลการเขียนใหม่ตรงตามlastจะหยุดการประมวลผลชุดปัจจุบันและคำขอเขียนใหม่จะถูกส่งผ่านอีกครั้งเพื่อค้นหาตำแหน่งที่เหมาะสม (และชุดใหม่ของกฎการเขียนใหม่) หากกฎสิ้นสุดด้วยbreakการเขียนใหม่ก็จะหยุดเช่นกัน แต่คำร้องขอที่เขียนใหม่จะไม่ถูกส่งไปยังตำแหน่งอื่น

นั่นคือถ้ามีสองสถานที่: loc1 และ loc2 และมีกฎการเขียนใหม่ใน loc1 ที่เปลี่ยน loc1 เป็น loc2 และจบลงด้วยlastคำขอจะถูกเขียนใหม่และส่งไปยังตำแหน่ง loc2 หากกฎสิ้นสุดด้วยbreakจะเป็นของตำแหน่ง loc1


คุณหมายถึงว่าการเขียนใหม่มีค่าสถานะพักมันจะไม่ค้นหาบล็อกตำแหน่งที่ตรงกันดังนั้นจึงเป็นของตำแหน่ง loc1
Martin Fjordvald

เผง แก้ไขแล้ว.
minaev

43

OP ต้องการตัวอย่าง สิ่งที่ @minaev เขียนนั้นเป็นเพียงส่วนหนึ่งของเรื่องราว! ดังนั้นเราไปที่นี่ ...

ตัวอย่างที่ 1: ไม่มีแฟล็ก (ตัวแบ่งหรือล่าสุด)

server {
    server_name example.com;
    root 'path/to/somewhere';

    location / {
        echo 'finally matched location /';
    }

    location /notes {
        echo 'finally matched location /notes';
    }

    location /documents {
        echo 'finally matched location /documents';
    }

    rewrite ^/([^/]+.txt)$ /notes/$1;
    rewrite ^/notes/([^/]+.txt)$ /documents/$1;
}

ผลลัพธ์:

# curl example.com/test.txt
finally matched location /documents

คำอธิบาย:

สำหรับrewriteธงเป็นตัวเลือก!

ตัวอย่างที่ 2: บล็อกตำแหน่งนอก (ตัวแบ่งหรือล่าสุด)

server {
    server_name example.com;
    root 'path/to/somewhere';

    location / {
        echo 'finally matched location /';
    }

    location /notes {
        echo 'finally matched location /notes';
    }

    location /documents {
        echo 'finally matched location /documents';
    }

    rewrite ^/([^/]+.txt)$ /notes/$1 break; # or last
    rewrite ^/notes/([^/]+.txt)$ /documents/$1; # this is not parsed
}

ผลลัพธ์:

# curl example.com/test.txt
finally matched location /notes

คำอธิบาย:

นอกบล็อกตำแหน่งที่ตั้งทั้งสองbreakและlastทำงานในลักษณะที่แน่นอน ...

  • ไม่มีการแยกวิเคราะห์เงื่อนไขอีกต่อไป
  • เอ็นจิ้นภายใน Nginx ไปที่ขั้นตอนต่อไป (ค้นหาการlocationจับคู่)

ตัวอย่างที่ 3: บล็อกตำแหน่งภายใน - "ตัวแบ่ง"

server {
    server_name example.com;
    root 'path/to/somewhere';

    location / {
        echo 'finally matched location /';
        rewrite ^/([^/]+.txt)$ /notes/$1 break;
        rewrite ^/notes/([^/]+.txt)$ /documents/$1; # this is not parsed
    }

    location /notes {
        echo 'finally matched location /notes';
    }

    location /documents {
        echo 'finally matched location /documents';
    }
}

ผลลัพธ์:

# curl example.com/test.txt
finally matched location /

คำอธิบาย:

ภายในบล็อกตำแหน่งที่ตั้งจะตั้งbreakค่าสถานะต่อไปนี้ ...

  • ไม่มีการแยกวิเคราะห์เงื่อนไขอีกต่อไป
  • เอ็นจิ้นภายใน Nginx ยังคงแยกวิเคราะห์locationบล็อกปัจจุบัน

ตัวอย่างที่ 4: บล็อกตำแหน่งภายใน - "สุดท้าย"

server {
    server_name example.com;
    root 'path/to/somewhere';

    location / {
        echo 'finally matched location /';
        rewrite ^/([^/]+.txt)$ /notes/$1 last;
        rewrite ^/notes/([^/]+.txt)$ /documents/$1;  # this is not parsed
    }

    location /notes {
        echo 'finally matched location /notes';
        rewrite ^/notes/([^/]+.txt)$ /documents/$1;  # this is not parsed, either!
    }

    location /documents {
        echo 'finally matched location /documents';
    }
}

ผลลัพธ์:

# curl example.com/test.txt
finally matched location /notes

คำอธิบาย:

ภายในบล็อกตำแหน่งที่ตั้งจะตั้งlastค่าสถานะต่อไปนี้ ...

  • ไม่มีการแยกวิเคราะห์เงื่อนไขอีกต่อไป
  • เอ็นจิ้นภายใน Nginx เริ่มมองหาการจับคู่ตำแหน่งอื่นตามผลลัพธ์ของrewriteผลลัพธ์
  • ไม่มีการแยกวิเคราะห์เงื่อนไขการเขียนอีกต่อไปแม้ในการจับคู่ตำแหน่งต่อไป!

สรุป:

  • เมื่อrewriteเงื่อนไขกับการตั้งค่าสถานะbreakหรือการlastแข่งขัน Nginx หยุดการแยกวิเคราะห์อีกต่อไปrewrites!
  • นอกบล็อกที่ตั้งด้วยbreakหรือlastNginx ทำงานเดียวกัน (หยุดการประมวลผลอีกครั้งเขียนเงื่อนไข)
  • ภายในบล็อกตำแหน่งด้วยbreakNginx จะหยุดการประมวลผลการเขียนเงื่อนไขอีกต่อไป
  • ภายในบล็อกตำแหน่งด้วยlastNginx หยุดการประมวลผลอีกครั้งเขียนเงื่อนไขแล้วเริ่มมองหาการจับคู่locationบล็อกใหม่! Nginx ยังเพิกเฉยrewritesต่อlocationบล็อกใหม่!

หมายเหตุสุดท้าย:

ฉันพลาดที่จะรวมกรณีขอบเพิ่มเติม (จริง ๆ แล้วปัญหาทั่วไปกับ rewrites เช่น500 internal error) แต่นั่นไม่ได้อยู่ในขอบเขตของคำถามนี้ อาจเป็นไปได้ว่าตัวอย่างที่ 1 อยู่นอกขอบเขตเช่นกัน!


ข้อผิดพลาด : "nginx.service ล้มเหลวเนื่องจากกระบวนการควบคุมออกโดยมีรหัสข้อผิดพลาด" ... คำสั่งที่ไม่รู้จัก "echo"
Peter Krauss

nginx.com/resources/wiki/modules/echo Linux ดิสทริบิวชันเช่น Ubuntu 14.04 เป็นต้นไปรวมโมดูลนี้ในบางแพ็คเกจ (เช่นใน nginx-extras) ฉันหวังว่าจะช่วย
Pothi Kalimuthu

1
ในตัวอย่างที่ 1 จะสร้างความแตกต่างหรือไม่หากวางกฎการเขียนซ้ำเหนือคำสั่งตำแหน่งทั้งสามนี้
Craig Hicks

1
@ CraigHicks ไม่มันจะไม่ กฎการเขียนซ้ำมีความสำคัญมากกว่าและดำเนินการในตอนแรกก่อนที่จะจับคู่สถานที่
Pothi Kalimuthu

1
นี่ควรเป็นคำตอบที่ดีที่สุด ง่ายต่อการเข้าใจโดยอ้างอิงจากตัวอย่างเหล่านี้และอ่านเอกสาร nginx
Don Dilanga
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.