कुकी का उपयोग करके Nginx प्रॉक्सी लक्ष्य को नियंत्रित करना?


11

मैं एक दिलचस्प अपाचे mod_rewrite सेटअप का उपयोग करके Nginx का उपयोग करने के बजाय एक रिवर्स प्रॉक्सी को बदलने की कोशिश कर रहा हूं (बाहरी चिंताओं के कारण हम Apache से Nginx में जा रहे हैं, और इस भाग को छोड़कर अधिकांश सब कुछ ठीक काम करता है)।

मेरा मूल सेटअप एक HTTP कुकी (कुछ एप्लिकेशन द्वारा निर्धारित) को पढ़ने के लिए था और इसके मूल्य के आधार पर, रिवर्स प्रॉक्सी को अलग-अलग बैकेंड पर निर्देशित करें। यह कुछ इस प्रकार रहा:

RewriteCond %{HTTP_COOKIE}  proxy-target-A
RewriteRule ^/original-request/ http://backend-a/some-application [P,QSA]

RewriteCond %{HTTP_COOKIE}  proxy-target-B
RewriteRule ^/original-request http://backend-b/another-application [P,QSA]

RewriteRule ^/original-request http://primary-backend/original-application [P,QSA]

मैं Nginx का उपयोग करके समान हासिल करने की कोशिश कर रहा हूं, और मेरा प्रारंभिक कॉन्फ़िगरेशन कुछ इस तरह था (जहां "प्रॉक्सी_ओवराइड" कुकी का नाम है):

location /original-request {
    if ($cookie_proxy_override = "proxy-target-A") {
        rewrite . http://backend-a/some-application;
        break;
    }
    if ($cookie_proxy_override = "proxy-target-B") {
        rewrite . http://backend-b/another-application;
        break;
    }
    proxy_pass http://primary-backend/original-application;
}

लेकिन ऐसा नहीं हुआ। मैंने यह देखने की कोशिश की है कि क्या नग्नेक्स प्राथमिक आधार पर रीडायरेक्ट करने के लिए मेरे कुकी को पढ़ सकता है, जिसके आधार पर ${cookie_proxy_override}मैं किसी चीज को रीडायरेक्ट कर सकता हूं और यह देख सकता हूं कि यह सामग्री ठीक पढ़ती है, लेकिन ifलगता है कि यह हमेशा विफल रही है।

मेरी अगली कोशिश, रिक्की के जवाब के अनुसार यह थी:

location /original-request {
    if ($http_cookie ~ "proxy-target-A") {
        rewrite . http://backend-a/some-application;
        break;
    }
    if ($http_cookie ~ "proxy-target-B") {
        rewrite . http://backend-b/another-application;
        break;
    }
    proxy_pass http://primary-backend/original-application;
}

और अब मैं देख सकता हूं कि ifब्लॉक सक्रिय हो गया है, लेकिन अनुरोध को अनुमानित करने के बजाय (जैसे मैंने सोचा था कि यह होगा) यह निर्दिष्ट URL पर 302 रीडायरेक्ट लौटाता है - जो मैं करने की कोशिश नहीं कर रहा हूं: मुझे सर्वर की आवश्यकता है पारदर्शी रूप से बैकएंड के लिए अनुरोध को रिले करें और मूल ग्राहक की प्रतिक्रिया को पाइप करें।

मैं क्या गलत कर रहा हूं?

जवाबों:


16

इस उत्तर के समान । इस तरह की समस्याओं के लिए Nginx का मुहावरेदार दृष्टिकोण है map

असल में, आप एक अनुभाग mapमें परिभाषित करते हैंhttp

map $cookie_proxy_override $my_upstream {
  default default-server-or-upstream;
  ~^(?P<name>[\w-]+) $name;
}

तब आप बस अनुभाग $my_upstreamमें उपयोग करते हैं location:

location /original-request {
  proxy_pass http://$my_upstream$uri;
}

नग्नेक्स केवल एक बार (प्रति अनुरोध) और जब आप उनका उपयोग कर रहे हैं, तो मानचित्र चर का मूल्यांकन करता है।


3
धन्यवाद, यह एक बेहतर दृष्टिकोण है मेरा, सबसे विशेष रूप से क्योंकि मैं नामित कुकी चर का सीधे उपयोग कर सकता हूं (यह सुनिश्चित नहीं है कि मैं क्यों नहीं कर सकता if) और मैंने इसे लागू किया। हालांकि एक समस्या है - नग्नेक्स (कम से कम मेरा संस्करण: 1.0.0) में गिने हुए कैप्चर पसंद नहीं है map, इसलिए मुझे ~^(?P<name>[\w-]+) $name;इसके बजाय उपयोग करना था। मैंने उसी के अनुसार आपका उत्तर संपादित किया है।
Guss

3

अंततः मेरा समाधान इस पर उबलता है:

server {
    ...
    set $upstream "default-server-or-upstream";
    if ($http_cookie ~ "proxy_override=([\w-]+)") {
        set $upstream $1;                                   
    }

    location /original-request {
        proxy_pass http://$upstream/original-application
    }
}

परीक्षण serverप्रत्येक अनुरोध के दायरे में किया जाता है (वास्तविक पुनर्निर्देशन से पहले) हल किया जाता है और बस एक चर सेट करने के लिए उपयोग किया जाता है - यह जाहिरा तौर पर Nginx "रीराइट" मॉड्यूल का एक समर्थित उपयोग है। यह पूरी $http_cookieतरह से @Rikih द्वारा सुझाए गए परीक्षणों का भी परीक्षण करता है , लेकिन इसमें यह सुनिश्चित करने के लिए कुकी का नाम भी शामिल है कि मैं यादृच्छिक सामान से मेल नहीं खाता जो लोग मुझ पर फेंक रहे होंगे।

फिर उस locationदायरे में जहां मैं पुनर्निर्देशित करना चाहता हूं, मैं चर नाम का उपयोग करता हूं जिसमें या तो डिफ़ॉल्ट अपस्ट्रीम कॉन्फ़िगरेशन शामिल है या कुकी द्वारा अधिलेखित किया गया था।


0

क्या आपने $ http_cookie की कोशिश की है? http://wiki.nginx.org/HttpRewriteModule

अगर ($ http_cookie ~ * "प्रॉक्सी-लक्ष्य-ए") {फू; }


कि वास्तव में परीक्षण के लिए काम किया, हालांकि मुझे यकीन नहीं है कि मैं सिर्फ विशिष्ट कुकी नाम के खिलाफ परीक्षण क्यों नहीं कर सकता। मुझे यह पसंद नहीं आया कि rewriteवास्तव में एक प्रॉक्सी फिर से लिखना नहीं है, बल्कि ग्राहक को पुनर्निर्देशित करता है, और मैं ifब्लॉक में प्रॉक्सी_पास का उपयोग नहीं कर सकता । मैंने अपने अनुसार सवाल अपडेट किया है।
Guss

0

मेरे पास नमूना है जो मैं udid के आधार पर अनुरोध हेडर का पता लगाने के लिए उपयोग करता हूं और यह काम कर रहा है, हो सकता है कि आपको कुछ विचार मिलेगा।

   location / {
      proxy_set_header Host $http_host;
  if ($request_uri ~ ^/(.*)udid=xxxxxxxxxxxxxx(.*)$) {
    proxy_pass   http://1.1.1.1$request_uri;
    break;
  }
  if ($request_uri ~ ^/(.*)udid=yyyyyyyyyyyyyy(.*)$) {
    proxy_pass   http://3.3.3.3$request_uri;
    break;
  }
       proxy_pass http://2.2.2.2$request_uri;
    }

Nginx के कौन से संस्करण का उपयोग कर रहे हैं? मैं 1.0 का उपयोग कर रहा हूं और जब मैं यहां आपके द्वारा निर्दिष्ट प्रॉक्सी_पास का उपयोग करता हूं, तो मुझे यह त्रुटि संदेश मिलता है:nginx: [emerg] "proxy_pass" may not have URI part in location given by regular expression, or inside named location, or inside the "if" statement, or inside the "limit_except" block in /etc/nginx/conf.d/proxy.conf:47
Guss

i nginx-0.8.53-1.el5
चोक्रिप्पल

हो सकता है कि आप एक मंच
chocripple

फ़ोरम में समाधान किसी अन्य सर्वर से प्रॉक्सिंग करते समय यूआरआई के अनुरोध को नहीं बदलना है, लेकिन यह वही है जो मुझे करने की आवश्यकता है - एक आवेदन को अलग से लक्षित करने के लिए यूआरआई को फिर से लिखना और फिर मूल URL में क्या शामिल है। इसके अलावा, आपका उदाहरण proxy_passकमांड में URI के अनुरोध का उपयोग करने के लिए भी लगता है , इसलिए मुझे यकीन नहीं है कि उपरोक्त फोरम चर्चा को देखते हुए यह आपके लिए कैसे काम कर सकता है।
Guss
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.