ฉันจะเขียน URL ใหม่ในการตอบสนองพร็อกซีใน NGINX ได้อย่างไร


87

ฉันคุ้นเคยกับการใช้ Apache กับ mod_proxy_html และกำลังพยายามทำสิ่งที่คล้ายกับ NGINX กรณีการใช้งานเฉพาะคือฉันมี UI ของผู้ดูแลระบบที่ทำงานใน Tomcat บนพอร์ต 8080 บนเซิร์ฟเวอร์ที่บริบทราก:

http://localhost:8080/

ฉันต้องการแสดงสิ่งนี้ในพอร์ต 80 แต่ฉันมีบริบทอื่น ๆ บนเซิร์ฟเวอร์ NGINX ที่ทำงานบนโฮสต์นี้ดังนั้นต้องการลองและเข้าถึงสิ่งนี้ที่:

http://localhost:80/admin/

ฉันหวังว่าบล็อกเซิร์ฟเวอร์ที่เรียบง่ายสุด ๆ ต่อไปนี้จะทำได้ แต่ก็ไม่มาก:

server {
    listen  80;
    server_name screenly.local.akana.com;

    location /admin/ {
        proxy_pass http://localhost:8080/;
    }
}

ปัญหาคือเนื้อหาที่ส่งคืน (html) มี URL ไปยังสคริปต์และข้อมูลรูปแบบที่เข้าถึงได้ทั้งหมดที่บริบทรูทดังนั้นฉันจึงต้องเขียน URL เหล่านี้ใหม่เพื่อเริ่มต้นด้วย / admin / แทน /

ฉันจะทำสิ่งนี้ใน NGINX ได้อย่างไร

คำตอบ:


128

ก่อนอื่นเราควรอ่านเอกสารเกี่ยวกับ proxy_passอย่างละเอียดและครบถ้วน

URI ที่ส่งไปยังเซิร์ฟเวอร์ต้นน้ำจะพิจารณาจากคำสั่ง "proxy_pass" ที่ใช้กับ URI หรือไม่ ต่อท้ายเฉือนใน proxy_pass สั่งหมายความว่า URI /เป็นปัจจุบันและเท่ากับ การไม่มีเครื่องหมายทับหมายความว่าไม่มี URI ของหมวก

Proxy_pass พร้อม URI :

location /some_dir/ {
    proxy_pass http://some_server/;
}

จากข้างต้นมีพร็อกซีดังต่อไปนี้:

http:// your_server/some_dir/ some_subdir/some_file ->
http:// some_server/          some_subdir/some_file

โดยทั่วไป/some_dir/ได้รับการแทนที่ด้วย/ที่จะเปลี่ยนเส้นทางการร้องขอจากไป/some_dir/some_subdir/some_file/some_subdir/some_file

Proxy_pass ที่ไม่มี URI :

location /some_dir/ {
    proxy_pass http://some_server;
}

ด้วยเครื่องหมายที่สอง (ไม่มีเครื่องหมายทับ): พร็อกซีจะเป็นดังนี้:

http:// your_server /some_dir/some_subdir/some_file ->
http:// some_server /some_dir/some_subdir/some_file

โดยทั่วไปเส้นทางคำขอดั้งเดิมแบบเต็มจะถูกส่งต่อโดยไม่มีการเปลี่ยนแปลง


ดังนั้นในกรณีของคุณดูเหมือนว่าคุณควรวางเครื่องหมายทับเพื่อให้ได้สิ่งที่คุณต้องการ


ข้อแม้

โปรดทราบว่าการเขียนซ้ำอัตโนมัติจะใช้ได้เฉพาะเมื่อคุณไม่ได้ใช้ตัวแปรใน proxy_pass หากคุณใช้ตัวแปรคุณควรเขียนตัวเองใหม่:

location /some_dir/ {
  rewrite    /some_dir/(.*) /$1 break;
  proxy_pass $upstream_server;
}

มีหลายกรณีที่การเขียนซ้ำใช้ไม่ได้นั่นคือเหตุผลที่ต้องอ่านเอกสารประกอบ


แก้ไข

อ่านคำถามของคุณอีกครั้งดูเหมือนว่าฉันอาจพลาดที่คุณต้องการแก้ไขเอาต์พุต html

ด้วยเหตุนี้คุณสามารถใช้คำสั่งsub_filter สิ่งที่ต้องการ ...

location /admin/ {
    proxy_pass http://localhost:8080/;
    sub_filter "http://your_server/" "http://your_server/admin/";
    sub_filter_once off;
}

โดยทั่วไปสตริงที่คุณต้องการแทนที่และสตริงแทนที่


2
ขอบคุณที่ช่วยได้มาก ฉันคิดว่า sub_filter จะทำ
IanG

2
ฉันอยากรู้ว่า nginx ได้เขียนเอาต์พุตใหม่ในระดับใดแล้วไม่จำเป็นต้องเขียนโฮสต์ / ชื่อโฮสต์ในลิงก์อย่างน้อยที่สุดอีกหรือ เช่นคุณจะไม่ทำsub_filter "http://localhost/" "http://localhost/admin/"
ThorSummoner

1
ในการอนุญาตให้เขียนใหม่นอกเหนือจากtext/htmlประเภท mimetype ฉันต้องเพิ่มsub_filter_types *;ด้วย
anttikoo

มีบางอย่างแปลก ๆ เกิดขึ้นกับฉันด้วยวิธีนี้ ทรัพยากร (* .js, * .css ฯลฯ กำลังถูกดึงข้อมูล) แต่ไม่สามารถโหลดหน้าเว็บได้ ฉันคาดหวังว่าhttp://your_server/admin/จะได้รับการแก้ไขhttp://your_serverระหว่าง proxy_pass แต่ไม่ได้และฉันได้รับข้อผิดพลาดreact-router /admin/ location did not match any routesในแอปพลิเคชันของฉันเนื่องจากแอปพลิเคชันของฉันไม่รู้อะไรเกี่ยวกับ '/ admin'
จี

คุณอาจต้องเพิ่มproxy_redirectคำสั่งเพื่อให้Locationส่วนหัวที่ส่งโดยการตอบกลับได้รับการแก้ไขตาม url ด้วย ตรวจสอบการกวดวิชานี้: cyberciti.biz/faq/...
vivanov

22

คุณอาจต้องตั้งค่าคำสั่งต่อไปนี้ก่อน "ตัวกรองย่อย" ตัวแรกสำหรับเซิร์ฟเวอร์แบ็กเอนด์ที่มีการบีบอัดข้อมูล:

proxy_set_header Accept-Encoding "";

มิฉะนั้นอาจไม่ทำงาน สำหรับตัวอย่างของคุณจะมีลักษณะดังนี้:

location /admin/ {
    proxy_pass http://localhost:8080/;
    proxy_set_header Accept-Encoding "";
    sub_filter "http://your_server/" "http://your_server/admin/";
    sub_filter_once off;
}

-1

คุณสามารถใช้ตัวอย่างการกำหนดค่า nginx ต่อไปนี้:

upstream adminhost {
  server adminhostname:8080;
}

server {
  listen 80;

  location ~ ^/admin/(.*)$ {
    proxy_pass http://adminhost/$1$is_args$args;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Host $server_name;
  }
}

1
เหตุใดจึงลดลง มีปัญหากับรหัสหรือไม่? ดูเหมือนจะเป็นวิธีแก้ปัญหาที่ดีและซับซ้อนสำหรับฉันการแก้ปัญหาบางประการของการพร็อกซีแอปที่จะปรากฏขึ้นในภายหลัง ไม่แน่ใจว่าทำไมproxy_redirect off;แม้ว่า ฉันจะเพิ่มproxy_set_header X-Forwarded-Proto $scheme;ด้วย
LuH
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.