Как правильно обрабатывать относительные URL с помощью обратного прокси

51

У меня есть обратный прокси-сервер настройки в Apache следующим образом:

Сервер A с адресом www.example.com/folder является обратным прокси-сервером.

Он сопоставляется с: Сервер B с адресом test.madeupurl.com

Этот вид работ. Но у меня проблема в том, что на www.example.com/folder все относительные ссылки имеют форму www.example.com/css/examplefilename.css, а не www.example.com/folder/css/examplefilename. CSS

Как я могу это исправить?

Пока мой обратный прокси-сервер имеет это на сервере A (www.example.com):

<Location /folder>
    ProxyPass  http://test.madeupurl.com
    ProxyPassReverse http://test.madeupurl.com
</Location>
Трудоголик
источник
Какое из приведенных ниже решений сработало для вас в ответе Брейна, если вы помните?
Кимберли W

Ответы:

81

Apache ProxyPassRewrite не переписывает тела ответов, полученные с http://test.example.com , а только заголовки (например, перенаправления на страницу 404 и т. Д.).

Ряд альтернатив:

Один ) Перепишите внутреннее приложение, чтобы использовать относительные пути вместо абсолютных. т.е. ../css/style.cssвместо/css/style.css

2 ) /folderПовторно разверните внутреннее приложение в том же подкаталоге, а не в корне test.example.com.

Три ) Один и два часто маловероятны ... Если вам повезло, внутреннее приложение использует только два или три подкаталога, и они не используются на вашем основном сайте , просто напишите несколько строк 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/

Четыре ) Создайте отдельный поддомен для внутреннего приложения и просто переверните все прокси:

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

Пять ) Иногда разработчики совершенно невежественные и имеют свои приложения не только генерировать абсолютный URL, но даже включать имя хоста часть в их URL, и результирующие HTML код выглядит следующим образом : <img src=http://test.example.com/icons/logo.png>.

A ) Вы можете использовать комбинированное решение DNS с разделением горизонта и сценария 4. Как внутренние, так и внешние пользователи используют test.example.com, но ваш внутренний DNS указывает непосредственно на ip-адрес сервера test.example.com. Для внешних пользователей общедоступная запись test.example.com указывает на IP-адрес вашего общедоступного веб-сервера www.example.com, и вы можете использовать решение 4.

B ) На самом деле вы можете заставить apache не только запрашивать прокси на test.example.com, но и переписать тело ответа, прежде чем оно будет передано вашим пользователям. (Обычно прокси переписывает только HTTP заголовки / ответы). mod_substitute в apache 2.2. Я не проверял, хорошо ли он сочетается с mod_proxy, но, возможно, работает следующее:

<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
источник
4
Святая корова хороший ответ. Даже не пробовал ничего из этого, но хотел сказать спасибо за рецензию! Помогает миллион. Собираюсь проверить некоторые из этих идей сейчас и вскоре сообщу об этом :)
Трудолюбивый
Быстрый вопрос, пожалуйста, для пункта 2, если я правильно вас понял, сэр, вы предлагаете мне повторно развернуть приложение adpp на test.madeupurl.com/folder? Требует ли это каких-либо изменений в моем конфигурационном файле apache? Это выглядит как самое быстрое решение
трудолюбивый
Кроме того, извините, что беспокою вас, но с пунктом 1, когда я пробую то, что вы предлагаете, проблема, которую я описал в моем вопросе, все еще сохраняется. Например, здесь я использовал: <link rel = "stylesheet" type = "text / css" href = "../ css / custom.css" /> и для адреса ссылки в браузере выводит test.madeupurl.com /css/bootstrap.css, а не test.madeupurl.com/folder/css/bootstrap.css . Если бы у вас были какие-либо предложения по этому вопросу, это было бы очень полезно
Трудолюбивый
Часто при повторном развертывании приложения, которое теперь установлено в DocumentRoot, в подкаталог, такой как / folder, таблицы стилей, значки и т. Д. Будут развернуты в / folder / css и / folder / icons и т. Д. Затем ссылки в выводе HTML станут похожими на <img src=/folder/icons/button.png>которые в очередь будет поймана ProxyPass /folder/ http://test.madeupurl.com/folder/директивой.
HBruijn
Страница test.madeupurl.com/content/index.html хочет включить test.madeupurl.com/css/custom.css. В этом месте вы должны использовать относительный URL, href="../css/custom.css"а не href="/css/custom.css". Когда пользователь Интернета извлечет страницу, URL-адрес будет www.example.com/folder/content/index.html. Тогда URL для css будет: www.example.com/folder/content/../css/custom.cssкоторый на самом деле www.example.com/folder/css/custom.cssбудет перенаправлен test.madeupurl.com/css/custom.css.
HBruijn
8

В дополнение к ответу HBruijn , если вы выбираете решение (3) «ProxyPass», вам, возможно, придется также использовать mod_proxy_html, чтобы переписать некоторые URL-адреса на ваших HTML-страницах.

ср Как правильно обрабатывать относительные URL с помощью обратного прокси-сервера для некоторых примеров.

В качестве прикладного примера, вот как вы можете настроить Apache, используя ProxyHTMLURLMapправило для пересылки всего с your-domain-name.com/pad на ваш экземпляр Etherpad, работающий локально на порту 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]

Лукас Кимон
источник
2
Имейте в виду, что mod_proxy_html включен только с Apache 2.4 и выше, где первоначальный вопрос выше относится к Apache 2.2
HBruijn
Ваш ответ безупречен. Тем не менее, я встречал случай, когда содержание не HTML, а скорее PDF. Использование ProxyHTMLURLMap не работает для меня. Любые другие предложения?
Мохамед Эннахди Эль Идрисси
2
Если ваш контент в формате PDF, вам не нужно переписывать URL-адреса в нем! Если вы не хотите, чтобы ваши пользователи нажимали на ссылки в PDF, чтобы получить доступ к другим страницам вашего сайта, но это звучит сложно. Чтобы отключить перезапись URL, просто опустите последние 2 директивы: SetOutputFilter& ProxyHTMLURLMap.
Лукас Кимон
Возможно, вам придется добавить RequestHeader unset Accept-Encoding, чтобы избежать ошибок кодирования
zar3bski
5

Вы можете использовать следующий способ создания обратного прокси:
1. Установите mod_proxy_html

    yum install mod_proxy_html
  1. Загрузить модуль mod_proxy_html

    LoadModule proxy_html_module modules/mod_proxy_html.so
    
  2. И используйте следующие настройки

    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>  
    

Надеюсь, это поможет.

ThanhHH
источник