apache proxy websocket meteor sockjs

¿Cómo configurar un proxy apache para Meteor/SockJS y WebSocket?



(5)

Desearía poder brindarte una respuesta directa con instrucciones de apache, pero como has mencionado nginx y el hecho es que es difícil de configurar, me gustaría analizar una alternativa que realmente usa nginx pero que te protege de todas las complejidades.

El tutorial en https://github.com/phusion/passenger/wiki/Phusion-Passenger:-Meteor-tutorial recorre los pasos para configurar Phusion Passenger con o sin nginx (internamente usa nginx de todos modos) para producción de varias instancias. Implementaciones de Meteor que pueden escalar para utilizar todos los núcleos en su servidor.

Es tan fácil como:

$ cd meteor-app-directory $ mkdir public tmp $ passenger start

Tengo un proxy Apache para una aplicación de meteoritos y Apache y Meteor están en dos máquinas separadas. Lo necesito así porque apache tiene que servir a muchos sitios web reales y no sería una buena idea instalar la aplicación de meteoritos en esta máquina debido a sus recursos limitados.

Sin embargo, el handshake de WebSocket falla con el código de respuesta 400 "Solo se puede actualizar a websocket" si intento conectarme desde el exterior a través del proxy. Todo funciona bien cuando me conecto desde la LAN directamente a la máquina meteórica. Cuando WebSocket falla, SockJS / Meteor vuelve a caer en XHR, pero desafortunadamente esto provoca algunos errores en la aplicación en cuestión. Entonces realmente necesito que WebSocket funcione en la mayoría de los casos.

Parcheé mi instalación de Apache con el parche mencionado aquí: https://stackoverflow.com/a/16998664 Parecía que iba bien, pero nada cambió ...

Mis directivas de proxy apache actualmente son las siguientes:

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/

E incluso sé lo que desencadena el problema. El proxy Apache se equivoca con el encabezado. El encabezado de solicitud original del paquete en cuestión que sale de mi máquina se ve así:

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

Mientras que el paquete se reenvía desde el proxy Apache de esta manera:

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

Por lo tanto, se elimina la "Actualización" y se altera la "Conexión", por lo que falla el saludo de la consola web. Ahora podría intentar configurar siempre "Actualizar" a "websocket" con una directiva RequestHeader. Sin embargo, esto no se siente bien y creo que traerá otros problemas y me preguntaba si existe una solución real a este problema. ¿O es esto algo de lo que debería tratar el parche de https://stackoverflow.com/a/16998664 y algo salió mal por mi parte aplicándolo?

Por lo que he leído, cambiar a nginx podría facilitar esta configuración. Consideraré esto, pero cuando sea posible, me gustaría hacer esto con Apache, ya que nginx haría otras cosas más complicadas y me costaría mucho tiempo.


Usamos esto para Apache y una aplicación SockJS detrás de Apache. Apache está haciendo el proxy WebSocket automáticamente, pero tiene que volver a escribir el esquema para ws; de lo contrario, recurre a XHR. Pero solo si la conexión es un apretón de manos de WebSocket. Agregar lo siguiente solucionará su problema :) (nota: cambie el localhost:3000 según su propia URL de backend).

RewriteEngine on RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC] RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC] RewriteRule .* ws://localhost:3000%{REQUEST_URI} [P]


Esta respuesta se basa en la respuesta de Fatih. Su solución falla para los navegadores que envían un encabezado de solicitud de conexión que no sea "Actualizar", como "keep-alive, Upgrade". Este fue el caso para mí con Firefox 42.

Para abordar el problema de Firefox también, cambie el apache RewriteCond de la siguiente manera:

RewriteEngine on RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC] RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC] RewriteRule .* ws://localhost:3000%{REQUEST_URI} [P]

( ^ Upgrade $ se convierte en Upgrade $ )

Quería poner esto como un comentario a la respuesta de Fatih, sin embargo carezco de la reputación necesaria.


Después de leer varias respuestas, publicar en el foro de Meteor, y un montón de pruebas aquí, está toda la enchilada que funcionó para mí. Las otras respuestas fueron algo incompletas, o al menos no funcionaron para mí.

Tenía que hacer:

sudo a2enmod proxy_wstunnel

También tuvo que agregar un ProxyPass y ProxyPassReverse y cambió ^ Actualizar $ a Actualizar $ de otra respuesta SO.

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

luego reinicia Apache.

Revisé en la consola y ahora no hay ningún error y no hay solicitudes xhr. Entonces supongo que está funcionando correctamente


La respuesta de Fatih-Arslan con la enmienda de Derwiwie funcionó a la perfección . Una cosa que tuve que usar fue poner wss en lugar de ws , porque mi servicio solo funciona en https.

RewriteEngine on RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC] RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC] RewriteRule .* wss://localhost:3000%{REQUEST_URI} [P]