Использование ProxyHTMLURLMap для перенаправления запросов CSS и JS

Вопрос или проблема

У меня уже установлен Apache 2.4.19 на Ubuntu 16.04, который работает с Tomcat. Я пытаюсь добавить приложение на Node и перенаправить все запросы к /node на http://localhost:3000 с помощью ProxyPass. Моё приложение на Node, конечно же, слушает порт 3000.

Это очень хорошо работает для перенаправления моих запросов, таких как https://myapi.com/node/foo

Однако у меня есть проблемы с документацией, созданной с помощью apidoc, которую я отдаю статически в своём приложении на Node, используя app.use(express.static('doc'));. Когда я перехожу по ссылке https://myapi.com/node, кажется, что все URLы такие как /vendor/xxx, /locales/xxx не получают префикс /node. Я думал, что ProxyHTMLURLMap должен с этим справиться, но, похоже, я использую его неправильно.

Вот мой файл /etc/apache2/sites-enabled/000-default.conf (я убрал некоторые комментарии, чтобы сделать его короче)

<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # Tomcat
    JkMount /* worker1

    # Конфигурация SSL
    SSLEngine on
    SSLCertificateFile /path/to/certificate
    SSLCertificateKeyFile /path/to/private.key
    SSLCACertificateFile /path/to/intermediate-cert

    # Заголовки
    Header always set Access-Control-Allow-Origin "*"
    Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding"
    Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PULL"
    # Возвращать 200 для всех запросов OPTIONS
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} OPTIONS
    RewriteRule ^(.*)$ $1 [R=200,L]

    # Обратный прокси для Node
    # Часть ниже должна была изменить относительный URL на /node/xxx, но, похоже, это не работает
    ProxyHTMLURLMap http://localhost:3000 /node
    <Location /node>
           ProxyPass http://localhost:3000
           ProxyPassReverse http://localhost:3000
           ProxyHTMLEnable On
           SetOutputFilter proxy-html
           ProxyHTMLURLMap http://localhost:3000
    </Location>
</VirtualHost>
<VirtualHost *:80>
    ServerName myapi.com
    Redirect / https://myapi.com/
</VirtualHost>

ИЗМЕНЕНИЕ
Я не могу использовать ProxyHTMLExtended On по совету Эндрю Шульмана, потому что это испортит вывод apidoc.js
index.html, сгенерированный с помощью apidoc.js, имеет это выражение в самом конце:
<script data-main="main.js" src="https://serverfault.com/questions/899237/vendor/require.min.js"></script>
Затем main.js делает кучу require
Я пытался заменить main.js на node/main.js в выражении скрипта, но тогда требуют ошибки…
Я также заметил, что если я напрямую запрашиваю https://myapi/node/index.html, все файлы, похоже, загрузились нормально. Возможно, я просто сконфигурирую Apache для перенаправления /node на /node/index.html

По умолчанию модуль mod_proxy_html не переписывает ссылки в встроенном CSS и Javascript. Чтобы это включить, вам нужно установить ProxyHTMLExtended On. Смотрите документацию.

Это может исправить вашу проблему, но это не затрагивает CSS и Javascript, которые загружаются из других файлов, а не включены встроенно. Если вы хотите попробовать исправить это тоже, вам нужно будет использовать другой модуль, такой как mod_sed или mod_line_edit. Это также может сработать для вас, но также может быть невозможно полностью исправить, так как в коде (т.е. Javascript) URL могут вычисляться произвольным образом, который регулярный парсер не может обнаружить.

Ответ или решение

Для решения вашей проблемы с перенаправлением запросов к Node.js приложению через Apache с использованием модуля mod_proxy_html, давайте рассмотрим ряд подходов.

Шаг 1: Настройка конфигурации Apache

Ваше текущее содержимое файла /etc/apache2/sites-enabled/000-default.conf можно немного изменить для правильной работы с ProxyHTMLURLMap. Основная проблема в том, что модули mod_proxy и mod_proxy_html могут не обрабатывать URL в ваших статических файлах CSS и JS должным образом из-за того, что они не включаются в пересылку. Вот как можно настроить конфигурацию:

<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # Tomcat
    JkMount /* worker1

    # SSL Config
    SSLEngine on
    SSLCertificateFile /path/to/certificate
    SSLCertificateKeyFile /path/to/private.key
    SSLCACertificateFile /path/to/intermediate-cert

    # Headers
    Header always set Access-Control-Allow-Origin "*"
    Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding"
    Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PULL"

    # Возвращение 200 для всех запросов OPTIONS
    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} OPTIONS
    RewriteRule ^(.*)$ $1 [R=200,L]

    # Обратный прокси к Node
    <Location /node>
        ProxyPass http://localhost:3000
        ProxyPassReverse http://localhost:3000
        ProxyHTMLEnable On
        SetOutputFilter proxy-html
        ProxyHTMLURLMap http://localhost:3000 /node
        ProxyHTMLURLMap / /node   # Добавить это правило
    </Location>
</VirtualHost>

<VirtualHost *:80>
    ServerName myapi.com
    Redirect / https://myapi.com/
</VirtualHost>

Шаг 2: Использование ProxyHTMLExtended

Поскольку вы упомянули, что не можете использовать ProxyHTMLExtended On, следует учитывать, что это может повлиять на корректность выводимого HTML. Однако, если это возможно сделать, попробуйте:

ProxyHTMLExtended On

Это позволит mod_proxy_html также обрабатывать ссылки внутри CSS и JavaScript, что может помочь с вашими проблемами при запросах к статическим ресурсам.

Шаг 3: Решение проблемы с ссылками

Если у вас есть необходимость изменить ссылки в статических файлах, которые не обрабатываются модулем mod_proxy_html, вы можете рассмотреть использование другого модуля Apache, такого как mod_sed или mod_line_edit. Эти модули могут редактировать содержимое страницы на лету, включая CSS и JavaScript файлы. Однако, стоит помнить, что такие решения могут быть сложными в настройке и не всегда гарантируют кросс-браузерную совместимость.

Шаг 4: Альтернативное решение

Если вы не можете заставить Apache правильно обрабатывать ссылки в статических файлах, то хорошей альтернативой было бы настроить в вашем Node.js приложении маршрутизацию. Например, вы можете создать отдельные маршруты в вашем Node.js приложении для обработки статических ресурсов, заменив их на /node/vendor/..., /node/locales/....

app.use('/node/vendor', express.static('vendor'));
app.use('/node/locales', express.static('locales'));

Заключение

Комбинируя предложенные выше методы, вы сможете настроить ваш сервер Apache так, чтобы он корректно перенаправлял запросы к Node.js, а также обрабатывал статические файлы без специальных модификаций в их коде. Всегда тестируйте изменения на локальной машине, чтобы убедиться в их работоспособности, прежде чем применять на рабочем сервере.

Оцените материал
Добавить комментарий

Капча загружается...