จะส่งต่อพารามิเตอร์สตริงการสืบค้นผ่าน proxy_pass ด้วย nginx ได้อย่างไร


114
upstream apache {
   server 127.0.0.1:8080;
}
server{
   location ~* ^/service/(.*)$ {
      proxy_pass http://apache/$1;
      proxy_redirect off;
   }
 }

ข้อมูลโค้ดด้านบนจะเปลี่ยนเส้นทางคำขอที่ URL รวมสตริง "service" ไปยังเซิร์ฟเวอร์อื่น แต่ไม่รวมพารามิเตอร์การค้นหา

คำตอบ:


163

จากเอกสารproxy_pass :

กรณีพิเศษกำลังใช้ตัวแปรในคำสั่ง proxy_pass: ไม่ได้ใช้ URL ที่ร้องขอและคุณมีหน้าที่รับผิดชอบอย่างเต็มที่ในการสร้าง URL เป้าหมายด้วยตัวคุณเอง

เนื่องจากคุณใช้ $ 1 ในเป้าหมาย nginx จึงต้องอาศัยคุณในการบอกสิ่งที่จะส่งผ่าน คุณสามารถแก้ไขได้สองวิธี ขั้นแรกการลอกจุดเริ่มต้นของ uri ด้วย proxy_pass นั้นไม่สำคัญ:

location /service/ {
  # Note the trailing slash on the proxy_pass.
  # It tells nginx to replace /service/ with / when passing the request.
  proxy_pass http://apache/;
}

หรือหากคุณต้องการใช้ตำแหน่ง regex เพียงแค่ใส่ args:

location ~* ^/service/(.*) {
  proxy_pass http://apache/$1$is_args$args;
}

1
ฉันไม่เชื่อว่าคุณจะทำได้อย่างหลัง ฉันพยายามและ nginx บ่นกับฉัน
ดูมา

3
บ่นว่าอย่างไร? ฉันเพิ่งทดสอบบน nginx 1.3.4 และทำงานได้ดีสำหรับฉัน
kolbyjack

ฮึ่ม .. ตอนนี้ฉันจำไม่ได้แล้ว :( แต่ฉันรู้สึกว่ามันอาจเกี่ยวข้องกับ "~ *" อย่างไรก็ตามฉันเพิ่งตรวจสอบและฉันมี nginx 1.2.3 (ผ่าน homebrew) ไม่แน่นะ?
duma

"proxy_redirect default" ไม่สามารถใช้กับคำสั่ง "proxy_pass" ที่มีตัวแปรได้
Jean-Philippe Caruana

1
ต้องใช้การเขียนซ้ำ location /service/ { rewrite ^\/service\/(.*) /$1 break; proxy_pass http://apache; }
Andrew Arnautov


10

ฉันแก้ไขโค้ด @kolbyjack เพื่อให้ใช้งานได้

http://website1/service
http://website1/service/

ด้วยพารามิเตอร์

location ~ ^/service/?(.*) {
    return 301 http://service_url/$1$is_args$args;
}

1
โปรดทราบว่านี่จะทำให้เซิร์ฟเวอร์ส่งคืนการตอบกลับ 301 ไปยังไคลเอนต์ก่อนที่จะเปลี่ยนเส้นทาง proxy_passสั่งดังกล่าวข้างต้นไม่เปลี่ยนเส้นทางในฝั่งเซิร์ฟเวอร์
Luke Peterson

1
สิ่งนี้จะพังหากพารามิเตอร์การค้นหาของคุณมีอักขระเข้ารหัส URL (%) ใช้คำตอบของแอนดรูว์แทน
David Weber

9

คุณต้องใช้การเขียนซ้ำเพื่อส่งผ่านพารามิเตอร์โดยใช้ proxy_pass นี่คือตัวอย่างที่ฉันทำสำหรับการปรับใช้แอพ angularjs กับ s3

S3 Static Website Hosting กำหนดเส้นทางเส้นทางทั้งหมดไปยัง Index.html

นำไปใช้กับความต้องการของคุณจะเป็นอย่างไร

location /service/ {
    rewrite ^\/service\/(.*) /$1 break;
    proxy_pass http://apache;
}

หากคุณต้องการสิ้นสุดในhttp://127.0.0.1:8080/query/params/

หากคุณต้องการสิ้นสุดในhttp://127.0.0.1:8080/service/query/params/ คุณจะต้องมีบางอย่างเช่น

location /service/ {
    rewrite ^\/(.*) /$1 break;
    proxy_pass http://apache;
}

1
ดูเหมือนว่าจะจัดการพา ธ params ( /path/params) ได้ดี แต่ไม่เคียวรี params ( ?query=params)?
จะ

อาไม่ฉันควรเพิ่มพารามิเตอร์การสืบค้นโดยอัตโนมัติ (อยู่ในการทดสอบของฉัน)
จะ

2

github gist https://gist.github.com/anjia0532/da4a17f848468de5a374c860b17607e7

#set $token "?"; # deprecated

set $token ""; # declar token is ""(empty str) for original request without args,because $is_args concat any var will be `?`

if ($is_args) { # if the request has args update token to "&"
    set $token "&";
}

location /test {
    set $args "${args}${token}k1=v1&k2=v2"; # update original append custom params with $token
    # if no args $is_args is empty str,else it's "?"
    # http is scheme
    # service is upstream server
    #proxy_pass http://service/$uri$is_args$args; # deprecated remove `/`
    proxy_pass http://service$uri$is_args$args; # proxy pass
}

#http://localhost/test?foo=bar ==> http://service/test?foo=bar&k1=v1&k2=v2

#http://localhost/test/ ==> http://service/test?k1=v1&k2=v2

1

หากต้องการเปลี่ยนเส้นทางโดยไม่มีสตริงการสืบค้นให้เพิ่มบรรทัดด้านล่างในบล็อกเซิร์ฟเวอร์ภายใต้ฟังพอร์ตบรรทัด:

if ($uri ~ .*.containingString$) {
           return 301 https://$host/$uri/;
}

ด้วยสตริงการสืบค้น:

if ($uri ~ .*.containingString$) {
           return 301 https://$host/$uri/?$query_string;
}

1
เอกสารคู่มือ nginx มีความชัดเจนเพื่อหลีกเลี่ยงการใช้ifเมื่อเป็นไปได้ ในกรณีนี้วิธีแก้ปัญหาสามารถใช้ได้locationตามที่แสดงในคำตอบอื่น
Andrés Morales

2
อย่างไรก็ตามอีกวิธีหนึ่งแม้ว่าจะมีข้อเสียก็ดีกว่า
Dmitry Malugin

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