Cara menangani url relatif dengan benar dengan proxy terbalik

51

Saya memiliki pengaturan proxy terbalik sebagai berikut di Apache:

Server A dengan alamat www.example.com/folder adalah server proxy terbalik.

Ini peta ke: Server B dengan alamat test.madeupurl.com

Jenis pekerjaan ini. Tetapi masalah yang saya miliki adalah, pada www.example.com/folder, semua tautan relatif adalah dari bentuk www.example.com/css/examplefilename.css alih-alih www.example.com/folder/css/examplefilename. css

Bagaimana cara saya memperbaikinya?

Sejauh ini proxy terbalik saya memiliki ini di Server A (www.example.com):

<Location /folder>
    ProxyPass  http://test.madeupurl.com
    ProxyPassReverse http://test.madeupurl.com
</Location>
Pekerja keras
sumber
Manakah dari solusi di bawah ini yang bekerja untuk Anda dalam jawaban HBruijn, jika Anda ingat?
Kimberly W

Jawaban:

81

Apache ProxyPassRewrite tidak menulis ulang badan tanggapan yang diterima dari http://test.example.com , hanya header (seperti pengalihan ke halaman 404 dan semacamnya).

Sejumlah alternatif:

Satu ) Tulis ulang aplikasi internal untuk menggunakan jalur relatif alih-alih absolut. yaitu ../css/style.cssbukannya/css/style.css

Dua ) Gunakan kembali aplikasi internal di subdirektori yang sama /folderdaripada di root test.example.com.

Tiga ) Satu dan dua sering tidak mungkin terjadi ... Jika Anda beruntung aplikasi internal hanya menggunakan dua atau tiga subdirektori dan itu tidak digunakan di situs utama Anda , cukup tulis banyak baris ProxyPass:

# Expose Internal App to the internet.
ProxyPass /externalpath/  http://test.example.com/
ProxyPassReverse /externalpath/  http://test.example.com/
# Internal app uses a bunch of absolute paths. 
ProxyPass /css/  http://test.example.com/css/
ProxyPassReverse /css/  http://test.example.com/css/
ProxyPass /icons/  http://test.example.com/icons/
ProxyPassReverse /icons/  http://test.example.com/icons/

Empat ) Buat subdomain terpisah untuk aplikasi internal dan cukup membalikkan semua proxy:

<VirtualHost *:80>
   ServerName app.example.com/
   # Expose Internal App to the internet.
   ProxyPass /  http://test.internal.example.com/
   ProxyPassReverse /  http://test.internal.example.com/
</VirtualHost>

Lima ) Terkadang pengembang sama sekali tidak tahu dan memiliki aplikasi mereka tidak hanya menghasilkan mutlak URL tetapi bahkan termasuk bagian hostname di mereka URL dan kode HTML yang dihasilkan terlihat seperti ini: <img src=http://test.example.com/icons/logo.png>.

A ) Anda dapat menggunakan solusi kombo DNS split horizon dan skenario 4. Pengguna internal dan eksternal menggunakan test.example.com, tetapi DNS internal Anda menunjuk langsung ke alamat ip server test.example.com. Untuk pengguna eksternal, catatan publik untuk test.example.com menunjuk ke alamat-ip server web publik Anda www.example.com dan Anda kemudian dapat menggunakan solusi 4.

B ) Anda benar-benar bisa mendapatkan apache ke tidak hanya permintaan proxy untuk test.example.com, tetapi juga menulis ulang badan respons sebelum akan dikirimkan ke pengguna Anda. (Biasanya proxy hanya menulis ulang HTTP header / response). mod_substitute di apache 2.2. Saya belum menguji apakah tumpukannya baik dengan mod_proxy, tapi mungkin yang berikut ini berfungsi:

<Location /folder/>
  ProxyPass http://test.example.com/
  ProxyPassReverse http://test.example.com/ 
  AddOutputFilterByType SUBSTITUTE text/html
  Substitute "s|test.example.com/|www.example.com/folder/|i" 
</Location>
HBruijn
sumber
4
Sapi suci jawaban yang bagus. Bahkan belum mencoba semua ini tetapi hanya ingin mengucapkan terima kasih untuk artikelnya! Membantu sejuta. Pergi untuk menguji beberapa dari ide-ide ini sekarang dan akan segera melaporkan kembali :)
Pekerja keras
Tolong, pertanyaan singkat, untuk poin 2 jika saya memahami Anda dengan benar, Anda menyarankan agar saya memindahkan kembali adpp ke test.madeupurl.com/folder? Apakah ini memerlukan perubahan pada file konfigurasi apache saya? Ini sepertinya solusi tercepat
Pekerja keras
Selain itu, maaf mengganggu Anda tetapi dengan poin 1 ketika saya mencoba apa yang Anda sarankan masalah yang saya jelaskan dalam pertanyaan saya masih berlanjut. Sebagai contoh di sini saya menggunakan: <link rel = "stylesheet" type = "text / css" href = "../ css / custom.css" /> dan untuk alamat tautan di browser ini adalah keluaran test.madeupurl.com /css/bootstrap.css daripada test.madeupurl.com/folder/css/bootstrap.css . Apakah Anda memiliki saran mengenai hal ini akan sangat membantu
Pekerja keras
Seringkali ketika Anda memindahkan aplikasi yang sekarang diinstal di DocumentRoot ke subdirektori seperti / folder stylesheet, ikon dll akan digunakan di / folder / css dan / folder / ikon dll. Kemudian tautan dalam output HTML akan menjadi seperti <img src=/folder/icons/button.png>di gilirannya akan ditangkap oleh ProxyPass /folder/ http://test.madeupurl.com/folder/arahan.
HBruijn
Halaman test.madeupurl.com/content/index.html ingin menyertakan test.madeupurl.com/css/custom.css. Di lokasi itu Anda harus menggunakan URL relatif href="../css/custom.css"dan tidak href="/css/custom.css". Ketika pengguna internet mengambil halaman, URL akan menjadi www.example.com/folder/content/index.html. URL untuk css akan menjadi: www.example.com/folder/content/../css/custom.cssyang sebenarnya www.example.com/folder/css/custom.cssakan diteruskan ke test.madeupurl.com/css/custom.css.
HBruijn
8

Sebagai pelengkap jawaban HBruijn , jika Anda memilih solusi (3) "ProxyPass", Anda mungkin juga harus menggunakan mod_proxy_html untuk menulis ulang beberapa URL di halaman HTML Anda.

lih. Cara menangani url relatif dengan benar dengan proxy terbalik untuk beberapa contoh.

Sebagai contoh terapan, di sini adalah bagaimana Anda dapat mengkonfigurasi Apache menggunakan ProxyHTMLURLMapaturan untuk meneruskan segala sesuatu di your-domain-name.com/pad untuk Anda EtherPad misalnya berjalan secara lokal pada port 9001:

<Location /pad> ProxyPass http://localhost:9001 retry=0 # retry=0 => avoid 503's when restarting etherpad-lite ProxyPassReverse http://localhost:9001 SetOutputFilter proxy-html ProxyHTMLURLMap http://localhost:9001 </Location> RewriteRule ^/pad$ /pad/ [R]

Lucas Cimon
sumber
2
Perlu diketahui bahwa mod_proxy_html hanya disertakan dari Apache 2.4 dan lebih tinggi, di mana pertanyaan asli di atas adalah untuk Apache 2.2
HBruijn
Jawaban Anda sempurna. Namun, saya bertemu kasus di mana kontennya bukan html, itu agak pdf. Menggunakan ProxyHTMLURLMap tidak berhasil untuk saya. Ada saran lain?
Mohamed Ennahdi El Idrissi
2
Jika konten Anda adalah PDF, Anda tidak perlu menulis ulang URL di dalamnya! Kecuali jika Anda ingin pengguna mengklik tautan dalam PDF untuk mengakses halaman lain dari situs web Anda, tetapi ini terdengar rumit. Untuk menonaktifkan penulisan ulang URL, cukup hapus 2 arahan terakhir: SetOutputFilter& ProxyHTMLURLMap.
Lucas Cimon
Anda mungkin perlu menambahkan RequestHeader tidak disetel Terima-Pengkodean untuk menghindari kesalahan pengodean
zar3bski
5

Anda dapat menggunakan cara berikut untuk membuat proxy terbalik:
1. Instal mod_proxy_html

    yum install mod_proxy_html
  1. Muat modul mod_proxy_html

    LoadModule proxy_html_module modules/mod_proxy_html.so
    
  2. Dan gunakan pengaturan berikut

    ProxyRequests off  
    ProxyPass /folder/  http://test.madeupurl.com  
    ProxyHTMLURLMap http://test.madeupurl.com  /folder  
    
    <Location /folder/>  
        ProxyPassReverse /  
        ProxyHTMLEnable On  
        ProxyHTMLURLMap  /  /folder/  
        RequestHeader    unset  Accept-Encoding  
    </Location>  
    

Semoga bantuan ini.

ThanhHH
sumber