Cómo forzar node.js / express.js a HTTPS cuando se ejecuta detrás de un equilibrador de carga de AWS

Estoy ejecutando un servicio de nodo / expreso en AWS y he implementado un ELB delante de él. Cuando enciendo una instancia de ELB con SSL habilitado, funciona para la primera página que golpeo, pero luego cambia a HTTP para cada acceso al servidor después de eso.

La regla de enrutamiento en el ELB termina el SSL y lo reenvía al puerto 8080 en el que el nodo está escuchando.

La solución de terminación SSL funcionará bien para mis propósitos, pero ¿cómo puedo mantener las llamadas de servidor subsiguientes en HTTPS?

He experimentado el mismo problema, pero en un contexto ligeramente diferente. Estaba implementando la aplicación Node.js / Express utilizando AWS Elastic Beanstalk y pude instalar un certificado SSL en ella.

El resultado de esto fue que mi aplicación estaba accesible en los protocolos http y https. La tabla de enrutamiento del equilibrador de carga se veía así:

 (Load balancer) http 80 --> (Node instance) http 8080 (Load balancer) https 443 --> (Node instance) http 8080 

Entonces, la pregunta era autorizar solo la conexión https en mi aplicación node.js, pero habilitar la redirección a https si la conexión se realizó inicialmente utilizando http.

Debido a que detrás del equilibrador de carga de AWS, todas las comunicaciones se realizan a través de http, una instrucción de redirección global (como un middleware en este caso) como esta crearía un bucle de redirección infinito:

 app.use(function(req, res, next) { if((!req.secure) && (req.protocol !== 'https')) { res.redirect('https://' + req.get('Host') + req.url); } } 

-> ¡simplemente porque la instrucción ( req.protocol !== 'https' ) siempre será verdadera!

De esta publicación del blog ( http://matthew.mceachen.us/blog/howto-force-https-with-amazon-elastic-load-balancer-and-apache-1071.html ), resulta que AWS ELB agrega un encabezado Proto Reenviado por X que puede capturar para saber cuál fue el protocolo utilizado antes del equilibrador de carga (http o https).

Así que esta pequeña modificación hizo el truco:

 app.use(function(req, res, next) { if((!req.secure) && (req.get('X-Forwarded-Proto') !== 'https')) { res.redirect('https://' + req.get('Host') + req.url); } else next(); }); 

¡Espero que esto ayude!