Я запускаю Apache 2.4.7 в качестве обратного прокси на Ubuntu 14.04 LTS. Этот сервер Apache действует как точка входа для множества различных серверных приложений, доступ к которым осуществляется через различные конфигурации mod_proxy в блоках
. Мне нужно предоставить обратный прокси-доступ для приложения, использующего WebSockets. Это приложение Java Spring, которое обслуживает HTML и другие статические файлы через HTTP, а затем использует WebSocket для динамических данных после загрузки страницы.
У меня есть приложение, работающее за Nginx
с использованием следующая конфигурация:
location /newapp/ {
proxy_pass http://newapp.example.com:8080/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
К сожалению, из-за необходимости модуля аутентификации Apache, который недоступен в Nginx, я не могу использовать его в производственной среде.
Я хочу сделать в псевдо-Apache-config:
<Location /newapp/>
if not WebSockets:
ProxyPass http://newapp.example.com:8080/
ProxyPassReverse /
else
ProxyPass ws://newapp.example.com:8080/
ProxyPassReverse /
</Location>
Модуль Apache mod_proxy_wstunnel
заставляет меня думать, что это должно быть возможно. Доступ к WebSocket осуществляется по URL-адресу / api / socket / ...
, поэтому я попытался разделить два типа ProxyPass
, используя отдельные
blocks:
<Location /newapp/>
ProxyPass http://newapp.example.com:8080/ disablereuse=on
ProxyPassReverse /
ProxyPassReverseCookieDomain newapp.example.com apps.example.com
ProxyPassReverseCookiePath http://newapp.example.com:8080/ /newapp/
</Location>
<Location /newapp/api/socket/>
ProxyPass ws://newapp.example.com:8080/api/socket/
ProxyPassReverse /
</Location>
Сначала это работает - браузер запрашивает http: //apps.example. com / newapp / , страница загружается через HTTP, статические ресурсы загружаются, код JavaScript подключается к веб-сокету, все в порядке.
Однако, когда новый запрос выполняется через HTTP - скажем, для GET /newapp/static/someimage.png
, что-то пошло не так. Этот запрос не соответствует местоположению WebSocket, поэтому я ожидаю, что он будет прокси-сервером с GET /static/someimage.png
до http://newapp.example.com:8080/
.
Вместо этого сервер приложений получает запрос на GET /newapp/static/someimage.png
и возвращает 404, поскольку это не тот URL, о котором он знает. Это нарушает работу приложения, поскольку HTTP-запросы, которые должны работать, вместо этого завершаются ошибкой.
Примечания:
GET / newapp / api / ajax / someapicall
также неправильно проксируется через прокси.
приводит к двум вещам: WebSocket не может подключиться и HTTP запросы продолжают работать. Я думаю, что происходит:
Я думаю, что mod_proxy_wstunnel
, после активации первым запросом на соответствие / newapp / api / socket /
, принимает на себя все последующие входящие запросы от клиента, независимо от того, соответствуют ли они Местоположение
или нет. Я проверил это, добавив RequestHeader set Test "some_identifying_value"
директиву к каждому Location
- HTTP-запросам для статических файлов и для / api / socket / info
заголовок Test
на них, но неправильно проксированные HTTP-запросы не прошли тест Test
заголовок на них, что говорит о том, что они передаются напрямую без обработки директивами Apache.
В конечном счете, мой вопрос таков: можно ли настроить любую версию Apache (я счастлив обновить!) до приложения на основе WebSocket с обратным прокси-сервером таким образом, чтобы HTTP-запросы также правильно проксировались через обратный прокси после подключения WebSocket? Если да, то как это настроено?
ответ Андерса дал мне 95% пути туда.
Основной сценарий:
newapp.example.com
/api/socket/
http://apps.example. com/newapp/
Вот как настроить WebSockets и обратное проксирование HTTP для вышеописанного сценария в блоке
:
<Location /newapp/>
ProxyPass http://newapp.example.com:8080/
ProxyPassReverse /
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule /api/(.*) ws://newapp.example.com:8080/api/$1 [P]
</Location>
Окончательное правило перезаписи очень важно - без него мы передадим запрос /newapp/api/socket
на WebSocket-сервер - который он отклонит.
Регекс разбирает все после api
- возможно, есть лучший способ перехватить этот блок, но это сработало. Затем мы должны помнить, что нужно переадресовать /api/
на конечный URL редиректа.
Самое главное, что HTTP-запросы продолжают работать после установления соединения с WebSocket!
.Я использую apache 2.4 в качестве прокси-сервера перед моим приложением весенней загрузки, это приложение обслуживает некоторые звонки api, вебсокеты (sockjs) и некоторые статические страницы. У меня были некоторые проблемы с заставкой вебсокета работать, секрет был в том, чтобы добавить правила перезаписи , которые вы видите ниже, теперь это работает на меня, моя конфигурация виртуального хоста apache выглядит так:
<VirtualHost *:443>
SSLEngine on
SSLCertificateFile /etc/httpd/ssl/my.crt
SSLCertificateKeyFile /etc/httpd/ssl/my.key
SSLCertificateChainFile /etc/httpd/ssl/intermediate.crt
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
ProxyRequests Off
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule .* ws://localhost:6868%{REQUEST_URI} [P]
ServerName my.dnsname.com
</VirtualHost>