Ubuntu 14.04 LTSでリバースプロキシとしてApache 2.4.7を実行しています。このApacheサーバーは、<Location>
ブロック内のさまざまなmod_proxy構成を介してアクセスされるさまざまなバックエンドアプリケーションへのエントリポイントとして機能します
WebSocketを使用するアプリケーションへのリバースプロキシアクセスを提供する必要があります。アプリケーションはJava HTTPを介してHTMLおよびその他の静的ファイルを提供するSpringアプリケーションであり、ページが読み込まれた後、動的データに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";
}
残念ながら、Nginxでは利用できないApache認証モジュールが必要なため、本番環境ではこれを使用できません。
私がしたいのは、pseudo-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/...
でアクセスされるため、別々の<Location>
ブロックを使用して2種類のProxyPass
を分離してみました。
<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コードはWebSocketに接続し、すべてが素晴らしいです。
ただし、新しいリクエストが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
も正しくプロキシされません。<Location /newapp/api/socket/>
セクションを無効にすると、WebSocketが接続に失敗し、HTTPリクエストが引き続き機能するという2つのことが起こります。私は何が起こっていると思います:
mod_proxy_wstunnel
は、/newapp/api/socket/
に一致する最初の要求によってアクティブ化されると、Location
に一致するかどうかにかかわらず、クライアントからのすべてのインバウンド要求を引き継ぐと思います。各Location
にRequestHeader set Test "some_identifying_value"
ディレクティブを追加してこれをテストしました-静的ファイルと/api/socket/info
のHTTPリクエストにはTest
ヘッダーがありましたが、プロキシされたHTTPリクエストにはTest
ヘッダーがありませんでした。これは、Apacheディレクティブで処理されずにそのまま渡されることを示しています。
結局のところ、私の質問は次のとおりです。Apacheの任意のバージョン(アップグレードしてよろしいですか?)を構成して、WebSocketの後にHTTPリクエストも正しくリバースプロキシされるように、WebSocketベースのアプリケーションをリバースプロキシすることができますか。接続されていますか?もしそうなら、これはどのように構成されていますか?
アンデルスの答えは私がそこに行く道の95%を得ました。
基本的なシナリオ:
newapp.example.com
にサーバーがあります/api/socket/
ですhttp://apps.example.com/newapp/
としてリバースプロキシしていますこれは、上記のシナリオの<Location>
ブロックでWebSocketと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サーバーに渡します-WebSocketサーバーは拒否します。
正規表現はapi
以降のすべてを解析しています-そのブロックをキャプチャするより良い方法があるかもしれませんが、これはうまくいきました。次に、/api/
を最終リダイレクトURLに再度追加することを忘れないでください。
最も重要なのは、WebSocket接続が確立された後もHTTPリクエストが引き続き機能することです。
私は自分のスプリングブートアプリの前でApache 2.4をプロキシとして使用しています。このアプリは、残りのAPI呼び出し、WebSocket(sockjs)、およびいくつかの静的ページを提供します。私はwebsocketを機能させるのにいくつかの問題を抱えていました、秘密を追加する必要がありました rewriteルール 以下を参照してください。
<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>