Meteor / SOCKJSおよびWebSocketのApacheプロキシを設定する方法
質問
私はMeteorアプリのApacheプロキシを持っていて、ApacheとMeteorは2つの別々のマシンにあります。 Apacheが多くの実際のウェブサイトを提供しなければならないように、それが必要とし、その限られたリソースのためにこのマシンにMeteorアプリをインストールすることは良い考えではありません。
しかし、WebSocketハンドシェイクは、プロキシを介して外部から接続しようとすると、応答コード400は「WebSocketにのみアップグレードできます」で失敗します。 LAN内から直接Meteorマシンに接続すると、すべてがうまく機能します。 WebSocketが失敗すると、SOCKJS / MeteorがXHRに戻りますが、残念ながらこれは問題のアプリ内のいくつかのバグをもたらします。だから私は本当にほとんどの場合に働くためのWebSocketが必要です。
ここで述べたパッチで私のApacheのインストールを修正しました: https://stackoverflow.com/a/a/16998664 それはうまくいったように見えましたが、何も変わっていません...
マイアパッチプロキシディレクティブ現在は次のとおりです。
ProxyRequests Off
ProxyPreserveHost On
ModPagespeed Off
<proxy>
Order deny,allow
Allow from all
</proxy>
ProxyPass / http://10.0.2.6:3000/
ProxyPassReverse / http://10.0.2.6:3000/
.
そして私は問題を引き起こされるのかを知っています。 Apacheプロキシはヘッダーと一緒にめちゃくちゃになります。マシンを残すという問題のパケットの元の要求ヘッダーは、次のようになります。
GET /sockjs/430/minw4r_o/websocket HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: myKey
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits, x-webkit-deflate-frame
User-Agent: My Agent
.
パケットがこのようなApacheプロキシから転送されます。
GET /sockjs/430/minw4r_o/websocket HTTP/1.1
Host: example.com
Origin: http://example.com
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: myKey
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits, x-webkit-deflate-frame
User-Agent: My Agent
X-Forwarded-For: 24.xxx.xxx.xxx
X-Forwarded-Host: example.com
X-Forwarded-Server: example.com
Connection: Keep-Alive
.
SO "アップグレード]が削除され、「接続」が変更され、WebSocketハンドシェイクが失敗します。これで、RequestHeaderディレクティブを使用して常に「アップグレード」を「WebSocket」に設定しようとすることができました。しかし、これは正しいとは感じていないと私はそれが他の問題を引き起こすだろうと思いますので、この問題に対する本当の解決策があるかどうか疑問に思いましたか?またはこれは https://stackoverflow.com/a/16998664 に対処し、何かが適用されるべきことに問題があるはずです。それは?
Nginxへの読み取りスイッチングがあるものからこの設定を容易にする可能性があります。私はこれを考慮しますが、可能な限り、Nginxが他のものをより複雑にし、私に多くの時間をかけているので、Apacheでこれをやりたいと思います。
解決
ApacheとApacheの背後にあるSockjsアプリにこれを使用します。ApacheはWebSocket Proxyを自動的に実行していますが、スキームをWSに書き換える必要があります。それ以外の場合は、XHRにフォールバックします。しかし、接続がWebSocketハンドシェイクの場合に限ります。次の問題を追加すると問題が解決されます。)(注:localhost:3000
をそれに応じて独自のバックエンドURLに変更します。
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^websocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade [NC]
RewriteRule .* ws://localhost:3000%{REQUEST_URI} [P]
. 他のヒント
この答えはFATIHの答えに基づいています。彼の解決策は、「キープアライブ、アップグレード」など、「アップグレード」以外の接続要求ヘッダーを送信するブラウザで失敗します。これはFirefox 42との場合でした。
Firefoxの問題に取り組むには、Apache Rewritecondを次のように変更します。
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule .* ws://localhost:3000%{REQUEST_URI} [P]
.
( ^アップグレード$ になるアップグレード$ )
これをFATIHの答えへのコメントとして貼りたかったが、私は必要な評判が欠けています。
いくつかの答えを読んだ後、ここではここで多くの試験を行っています。他の答えはやや不完全でした、あるいは少なくとも私のために働かなかった。
私はやらなければならなかった:
sudo a2enmod proxy_wstunnel
.
はまた、ProxyPassとProxyPassReverseを追加し、変更された^ Upgrade $を別の答えからアップグレードする必要がありました。
<VirtualHost *:80>
ServerName some-domain.com
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule .* ws://localhost:3000%{REQUEST_URI} [P]
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
</VirtualHost>
.
その後Apacheを再起動します。
コンソールをチェックし、現在エラーが発生していないため、XHR要求はありません。だから私はそれが正しく機能していると思います
Apache命令で直接返信を提供できることを願っていますが、NGINXを述べていて、事実が設定が難しいので、実際にNGINXを使用する代替手段で重量をしたいのですが。すべての複雑さからあなたを守る。
fatih-arslan Derwiwie さんの修正は魅力のように機能しました。 私のサービスがhttpsでのみ機能するため、私のサービスが ws>の代わりに wss を置くものであったのは、
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule .* wss://localhost:3000%{REQUEST_URI} [P]
.