พร็อกซี Nginx ตามวิธีการร้องขอ


17

เป็นไปได้ / ฉันจะกำหนดค่าตำแหน่งบล็อก Nginx เป็นพร็อกซีไปยังแบ็กเอนด์ที่แตกต่างกันได้หรือไม่ขึ้นอยู่กับวิธีการร้องขอ (เช่น GET / POST)

เหตุผลก็คือตอนนี้ฉันกำลังจัดการกับ 2 วิธีที่ 2 URL ที่ต่างกัน (อันเดียวผ่าน http proxy และอีกทางผ่าน fcgi) และฉันพยายามทำให้มันมากขึ้น "REST" ful ดังนั้นจะเป็นการดีที่สุดที่จะให้ทรัพยากรกลับรายการ ในขณะที่โพสต์ไปยังทรัพยากรเดียวกันควรเพิ่มลงในรายการ

คำตอบ:


27

ฉันไม่ได้ใช้การกำหนดค่านี้ แต่อ้างอิงจากตัวอย่างที่นี่ :

location /service  {
  if ($request_method = POST ) {
    fastcgi_pass 127.0.0.1:1234;
  }

  if ($request_method = GET ) {
     alias /path/to/files;
  }
}

หากคุณเขียนแอปพลิเคชันของคุณเองคุณสามารถลองตรวจสอบ GET / POST และส่งส่วนหัวX-Accel-Redirectเพื่อส่งไฟล์ไปยัง nginx


บล็อก GET เป็น proxy_pass ในกรณีของฉัน แต่อย่างอื่นก็ใช้งานได้ ในขณะนี้ฉันไม่ได้ใช้บล็อกที่สองหาก nginx ดูเหมือนจะหยุด "กำลังประมวลผล" เมื่อถึงคำสั่ง fastcgi_pass (เช่นไม่ผ่านและเรียกใช้พรอกซีพร็อกซีด้วย) เพราะฉันต้องการสิ่งอื่นนอกเหนือจาก POST เพื่อเปลี่ยนกลับ ไปยังพร็อกซี่
Brenton Alker

2
โปรดทราบว่าifเอกสารต้นฉบับของ Nginx ไม่สนับสนุน: nginx.com/resources/wiki/start/topics/depth/ifisevil
vog

1
ดังนั้นทางเลือกคืออะไร?
WM

1
@WM ดูคำตอบของฉัน: serverfault.com/a/823053/175421
vog

@vog น่าสนใจ วิธีที่ชาญฉลาดในการทำ ขอบคุณสำหรับการแบ่งปัน.
WM

23

แม้ว่าคุณจะสามารถทำสิ่งนี้ได้ifแต่สิ่งนี้ไม่ได้รับการสนับสนุนจากเอกสาร Nginxเนื่องจากifไม่สามารถทำงานได้ดีกับคำสั่งอื่น ๆ ตัวอย่างเช่นสมมติว่า GET ควรเปิดให้ทุกคนในขณะที่ POST ใช้สำหรับผู้ใช้ที่ได้รับการรับรองความถูกต้องเท่านั้นโดยใช้ HTTP Basic Auth ที่จะต้องifรวมกับauth_basicซึ่งไม่ทำงานอย่างถูกต้อง

นี่คือทางเลือกที่ใช้งานไม่ifได้ เคล็ดลับคือการใช้ "GET" และ "POST" เป็นส่วนหนึ่งของชื่ออัปสตรีมดังนั้นสิ่งเหล่านี้สามารถแก้ไขได้ด้วยการแทนที่ตัวแปร:

http {
  upstream other_GET {
    server ...;
  }
  upstream other_POST {
    server ...;
  }
  server {
    location /service {
      proxy_pass http://other_$request_method;
    }
  }
}

หากต้องการรวมสิ่งนี้กับ HTTP Basic Auth สำหรับทุกสิ่งยกเว้น GET เพียงเพิ่มlimit_exceptบล็อก:

  ...
    location /service {
      proxy_pass http://other_$request_method;
      limit_except GET {
        auth_basic ...;
      }
    }
  ...

ปัญหาของวิธีนี้คือตอนนี้เราจะกลับมา502 gateway errorเพราะno resolver defined to resolve other_HEAD(หรืออะไรก็ตามที่ขาดหายไปของคุณคือ) 405 method not allowedมันจะเป็นความหมายมากขึ้นเพื่อกลับสิ่งที่ต้องการ มีวิธีการทำสิ่งนี้หรือไม่?
James

1
@ James: นี่อาจจะเป็นวลีที่เป็นคำถามใหม่หมายถึงคำถามนี้ ฉันไม่มีคำตอบสำหรับรายละเอียดนี้ แต่คนอื่นอาจจะ
VOG

0

นี่คือสิ่งที่ฉันทำเพื่อให้สิ่งต่าง ๆ ทำงานให้ฉัน

add_header Allow "GET, POST, HEAD" always;
if ( $request_method !~ ^(GET|POST|HEAD)$ ) {
    proxy_pass http://back-end;
}

จอยสลับไปมาระหว่างสองจุดปลายทางอย่างแน่นอนตามวิธีการร้องขอหรือไม่?
พื้นฐาน

0

เปลี่ยนเล็กน้อยเป็นคำตอบของ vog เพื่อรวมตัวจัดการเริ่มต้นสำหรับวิธีการอื่น ๆ เช่น OPTIONS, PUT และอื่น ๆ

    upstream webdav_default {
            server example.com;
    }
    upstream webdav_upload {
            server example.com:8081;
    }
    upstream webdav_download {
            server example.com:8082;
    }
    server {
            map upstream_location $request_method {
                    GET     webdav_download;
                    HEAD    webdav_download;
                    PUT     webdav_upload;
                    LOCK    webdav_upload;
                    default webdav_default;
            }
            location / {
                    proxy_pass https://$upstream_location;
            }
    }

0

ฉันไม่สามารถรับคำตอบจาก @timmmmmy ให้ทำงานได้ แต่มันชี้ไปที่เอกสารของแผนที่และสิ่งนี้ใช้ได้กับฉัน:

map $request_method $upstream_location {
   PUT     example.com:8081;
   POST    example.com:8081;
   PATCH   example.com:8081;
   default example.com:8082;
}
server {
   location / {
      proxy_pass https://$upstream_location;
   }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.