सवाल Nginx proxy_pass के साथ पथ को कैसे निकालें


मेरे पास एक चल रहा वेब-एप्लिकेशन है http://example.com/, और एक अलग सर्वर पर, एक और अनुप्रयोग "माउंट" करना चाहते हैं http://example.com/en। अपस्ट्रीम सर्वर और proxy_pass काम करने लगते हैं, लेकिन एक मुद्दे के लिए:

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location /en {
    proxy_pass http://luscious;
  }
}

खोलने पर example.com/en, मेरा अपस्ट्रीम एप्लिकेशन रिटर्न 404 not found /en। यह समझ में आता है, क्योंकि अपस्ट्रीम में पथ नहीं है /en

है proxy_path सही समाधान? क्या मुझे "अपस्ट्रीम" को फिर से लिखना चाहिए ताकि यह सुन सके /en इसके बजाय, यह रूट पथ के रूप में? या क्या कोई निर्देश है जो मुझे अपस्ट्रीम के साथ पारित पथ को फिर से लिखने की अनुमति देता है?


47
2017-12-20 15:17


मूल




जवाब:


यह किसी भी नियमित अभिव्यक्ति के उपयोग के बिना, आप जो चाहते हैं उसे करने का सबसे प्रभावी तरीका है:

location = /en {
    return 302 /en/;
}
location /en/ {
    proxy_pass http://luscious/;  # note the trailing slash here, it matters!
}

92
2017-12-21 03:09



जहां तक ​​मुझे पता है, आखिरी हिस्सा अभी भी प्रॉक्सी के साथ पथ के रूप में "/ en" पास करेगा, नहीं? - berkes
@berkes, नहीं, यह नहीं होगा - पीछे पीछे स्लैश proxy_pass क्या एक फर्क पड़ता है। साथ ही, यह उत्तर आपके द्वारा आने वाले किसी भी से अधिक सही है, क्योंकि यह भी सुनिश्चित करता है proxy_redirect पर रहता है default, तो, आप अभी भी उपयोग कर सकते हैं 302 एट अल अपने बैकएंड के भीतर, और यह हर जगह सही ढंग से काम करते हैं। - cnst
आह, मैं पिछली स्लैश लापता था :( - Vanuan
Aaargh! अनुगामी स्लेश ! - barrymac
खोज के 3 घंटे, और हाँ ... यह पिछला स्लैश था। धन्यवाद दोस्त! - Lucas P.


मैं एक नए रेगेक्स-आधारित उत्तर को संबोधित करना चाहता हूं जो लोकप्रियता में बढ़ रहा है।

location ~ ^/en(/?)(.*)$ {  # OOPS!
  proxy_pass http://luscious/$2$is_args$args;  # OOPS!
}

समाधान पहली नज़र में अधिक प्यारा प्रतीत हो सकता है, लेकिन यह कई कारणों से गलत है।

  • उपरोक्त रेगेक्स एक अनुरोध यूरी से मेल खाता है /enjoyइसे रीडायरेक्ट कर रहा है /joy नदी के ऊपर। क्या यह वास्तव में इरादा है?

  • के लिए एक अनुरोध /en किसी भी रीडायरेक्ट का परिणाम नहीं होगा, सीधे सेवा करेगा / अपस्ट्रीम से (लगभग एक अनुरोध के रूप में /en/ इसके बजाय बनाया गया था, लेकिन काफी नहीं)। यदि आप अपने मूल पृष्ठ अपस्ट्रीम के भीतर सापेक्ष यूआरआई का उपयोग करते हैं (अन्यथा, आपके पास क्यों नहीं होगा /en/ अपस्ट्रीम यूआरआई के भीतर ठीक उपसर्ग?), उदा। src="style.css" (जो एक भाषा-विशिष्ट संदर्भित कर सकता है url("menu.png"), उदाहरण के लिए), तो ब्राउज़र उस के रूप में अनुरोध करेगा /style.css के बजाय /en/style.css। (या यदि आप हर जगह पूर्ण यूआरआई का उपयोग करते हैं, तो क्या होगा यदि कोई अपेक्षाकृत एक अस्पष्ट अर्ध-वैकल्पिक संसाधन का संदर्भ देता है?) ओह, अचानक साइट काम नहीं कर सकती है, लेकिन केवल कभी-कभी या किनारे के मामलों में।

  • मेरे अनुसार पहले से ही ओपी के अपने उत्तर द्वारा वर्णित एक और प्रश्न पर सलाह, नियमित अभिव्यक्तियों का उपयोग करके रोकता है proxy_redirect का डिफ़ॉल्ट मान होने का निर्देश default, इसे नीचे मोड़ना off बजाय। इसका मतलब है कि अगर अपस्ट्रीम के साथ जवाब मिलता है Location: http://127.0.0.1:8080/en/dir/ जब के लिए एक अनुरोध /en/dir बनाया जाता है, तो ग्राहक यही देखेगा, जो स्पष्ट रूप से सही ढंग से काम नहीं करेगा। (जो विशेष रूप से एक के लिए विडंबनापूर्ण होता /en अनुरोध जो पहले स्थान पर रेगेक्स उपयोग को संकेत देता है, फिर भी इस विशिष्ट कार्यान्वयन को उपरोक्त वर्णित किसी अन्य समस्या से पीड़ित है।) इसके अलावा, यदि आप पहले से ही उपयोग कर रहे हैं upstream निर्देश, तो अगर आप एक कस्टम के साथ जाने का प्रयास करते हैं, तो यह अतिरिक्त बदसूरत हो सकता है, खासकर अगर आपके पास एक से अधिक अपस्ट्रीम सर्वर हो - तो आपके पास अलग कैसे है proxy_redirect उनमें से प्रत्येक के लिए? आप भीतर नियमित अभिव्यक्तियों का उपयोग कर सकते हैं proxy_redirect, शायद, किसी भी मेजबान से मेल खाने के लिए भी, लेकिन फिर यदि आप भविष्य में एक क्रॉस-डोमेन रीडायरेक्ट देने का निर्णय लेते हैं तो क्या होगा?

उपरोक्त कुछ बिंदुओं को एक रेगेक्स-आधारित स्थान के साथ संबोधित करने का प्रयास करने के लिए, हम निम्नलिखित कार्य कर सकते हैं (ध्यान दें कि अंदर proxy_pass हमें एक सर्वर से संदर्भ को भी छोड़ना पड़ा upstreamबनाने के लिए निर्देशित निर्देश proxy_redirect अधिक सरल):

location ~ ^/en/?((?<=/).*)?$ {
  location = /en { return 302 /en/; }
  proxy_pass http://127.0.0.1:8080/$1$is_args$args;
  proxy_redirect http://127.0.0.1:8080/ /en/;
}

तो, अगर तुम मुझसे पूछो, तो दो भाई शीर्ष-स्तरीय स्थानों के साथ मूल समाधान इसके बजाय रेगेक्स मार्ग पर जाकर खुद को एक खरगोश छेद में खोदने से बेहतर विचार होगा।


11
2017-10-14 04:51



यह एक अपवाद का कारण बनता है: nginx: [emerg] location "/en" is outside location "^/en/?((?<=/).* - Athlan
@ एथलान, ऐसा इसलिए है क्योंकि आपको वास्तव में पहले स्थान पर इसका उपयोग नहीं करना चाहिए! यदि आप अभी भी चाहते हैं, तो आप उस स्थान को regexp के बाहर रख सकते हैं। - cnst
स्थानीयकरण = / एन बाहर काम करता है वास्तव में ठीक है! धन्यवाद - Sebastian Webber


तो, मैंने पाया stackoverflow पर जवाब:

upstream luscious {
 server lixxxx.members.linode.com:9001;
}

server {
  root /var/www/example.com/current/public/;
  server_name example.com;

  location ~ ^/en(/?)(.*) {
    proxy_pass http://luscious/$2;
  }
}

असल में: स्थान में रेगेक्स पास करना और proxy_pass url के साथ बैकफ्रफ़ पास करना।


6
2017-12-20 15:30



मुझे लगता है "proxy_pass सुस्वाद / $; "proxy_pass होना चाहिए" सुस्वाद / $ 2" - Zafer
@ ज़फर सही है, उपर्युक्त उत्तर मुझे एक त्रुटि दे रहा था - franck
मैंने जवाब बदल दिया है, लेकिन मेरे पास एक सर्वर नहीं है जहां मैं इसे आजमा सकता हूं, एटीएम, इसलिए यह सत्यापित नहीं है। - berkes