मैं NGINX में एक प्रॉक्सी प्रतिक्रिया में URL को कैसे फिर से लिखता हूं


86

मैं mod_proxy_html के साथ अपाचे का उपयोग करने के लिए उपयोग किया जाता हूं, और NGINX के साथ कुछ समान हासिल करने की कोशिश कर रहा हूं। विशिष्ट उपयोग मामला यह है कि मेरे पास एक प्रशासक यूआई है जो मूल संदर्भ में एक सर्वर पर पोर्ट 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 को / व्यवस्थापक / के बजाय शुरू करने के लिए फिर से लिखना होगा।

मैं NGINX में यह कैसे करूँ?

जवाबों:


121

हमें पहले प्रॉक्सी_पास पर दस्तावेज़ को ध्यान से और पूरी तरह से पढ़ना चाहिए ।

URI को अपस्ट्रीम सर्वर पर पारित किया जाता है, यह इस आधार पर निर्धारित किया जाता है कि "प्रॉक्सी_पास" निर्देश का उपयोग URI के साथ किया गया है या नहीं। प्रॉक्सी_पास के निर्देश में अनुगामी स्लैश का मतलब है कि यूआरआई मौजूद है और इसके बराबर है /। अनुगामी स्लेश का मतलब है कि टोपी यूआरआई अनुपस्थित है।

URI के साथ Proxy_pass :

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

URI के बिना Proxy_pass :

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

मूल रूप से, पूर्ण मूल अनुरोध पथ बिना किसी बदलाव के पास हो जाता है।


तो, आपके मामले में, ऐसा लगता है कि आपको केवल जो कुछ भी चाहिए उसे प्राप्त करने के लिए ट्रेलिंग स्लैश को छोड़ देना चाहिए।


चेतावनी

ध्यान दें कि यदि आप प्रॉक्सी_पास में चर का उपयोग नहीं करते हैं तो स्वत: फिर से लिखना ही काम करता है। यदि आप चर का उपयोग करते हैं, तो आपको अपने आप को फिर से लिखना चाहिए:

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

ऐसे और भी मामले हैं जहाँ फिर से काम नहीं होगा, इसीलिए प्रलेखन पढ़ना एक आवश्यक है।


संपादित करें

आपके प्रश्न को फिर से पढ़ते हुए, ऐसा लगता है कि मुझे याद आ गया है कि आप केवल html आउटपुट को संपादित करना चाहते हैं।

उसके लिए, आप उप_फिल्टर निर्देशन का उपयोग कर सकते हैं । कुछ इस तरह ...

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

मूल रूप से, वह स्ट्रिंग जिसे आप बदलना चाहते हैं और प्रतिस्थापन स्ट्रिंग


2
धन्यवाद, जो बहुत मदद करता है। मुझे लगता है कि सब_फिल्टर कर देगा।
इयानग सिप

2
मैं उत्सुक हूं कि nginx किस हद तक पहले से ही आउटपुट को फिर से लिख रहा है, यह नहीं है कि इसे कम से कम लिंक में होस्ट / होस्टनाम लिखना होगा? तो उदाहरण के लिए, आपsub_filter "http://localhost/" "http://localhost/admin/"
ThorSummoner

1
text/htmlMimetype के अलावा अन्य पुनर्लेखन की अनुमति देने के लिए , मुझे भी जोड़ना होगा sub_filter_types *;
अट्टिक्कू

इस समाधान के साथ मेरे लिए कुछ अजीब हो रहा है। संसाधन (* .js, * .css आदि प्राप्त हो रहे हैं), लेकिन पेज लोड होने में विफल रहता है। मैं प्रॉक्सी_पास के दौरान http://your_server/admin/हल होने की उम्मीद http://your_serverकरूंगा लेकिन यह react-router /admin/ location did not match any routesमेरे आवेदन में त्रुटि नहीं करता है और क्योंकि मेरे आवेदन को '/ व्यवस्थापक' के बारे में कुछ भी पता नहीं है।
प्राची

आपको proxy_redirectनिर्देश भी जोड़ने की आवश्यकता हो सकती है ताकि Locationप्रतिसाद द्वारा भेजे गए हेडर को भी url के अनुसार संशोधित किया जा सके। इस ट्यूटोरियल को देखें: cyberciti.biz/faq/…
vivanov

21

डेटा संपीड़न के साथ बैकएंड-सर्वर के लिए पहले "सब_फिल्टर" से पहले आपको निम्न निर्देश की आवश्यकता हो सकती है:

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;
}

-2

आप निम्न 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;
लुह
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.