Node.JS, Express y Heroku: ¿cómo manejar HTTP y HTTPS?

Tengo una aplicación que es la aplicación Express bastante normal: lógica de servidor simple, vistas, gran cantidad de JS del lado del cliente. Tengo que hacer muchas solicitudes de AJAX. Algunos de ellos deben estar protegidos por el protocolo HTTPS (otros no).

Por lo tanto, mi servidor debería funcionar tanto con HTTP como con HTTPS. También debería funcionar tanto en la máquina local (normalmente con nodemon) como en Heroku.

Por lo que he entendido, Heroku te da un solo puerto (process.env.PORT) que puedes escuchar y maneja todas las solicitudes a través del proxy (entonces, tu aplicación está escuchando este puerto y no se preocupa por el protocolo, ¿verdad? )

Entonces, ¿estoy entendiendo esto? ¿Debería tener algún código diferente para dev machine y Heroku?

Me gusta

... app = express() ... if process.env.NODE_ENV == 'production' app.listen(process.env.PORT) else https = require('https') http = require('http') http.createServer(app).listen(5080) # some local port options = { key: fs.readFileSync('key.pem'), cert: fs.readFileSync('cert.pem') # my self-signed files } https.createServer(options, app).listen(5443) # some different local port 

¿Es la forma correcta de lidiar con esto?

Para los desafíos de Coffeescript, aquí hay una versión de la respuesta de la Guardia convertida a Javascript. Tomé un enfoque diferente para dividir las declaraciones if else.

 var express = require('express'); var http = require('http'); var https = require('https'); var fs = require('fs'); var privateKey = fs.readFileSync('./config/localhost.key').toString(); var certificate = fs.readFileSync('./config/localhost.crt').toString(); var options = { key : privateKey , cert : certificate } var app = express(); // Start server. var port = process.env.PORT || 3000; // Used by Heroku and http on localhost process.env['PORT'] = process.env.PORT || 4000; // Used by https on localhost http.createServer(app).listen(port, function () { console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env); }); // Run separate https server if on localhost if (process.env.NODE_ENV != 'production') { https.createServer(options, app).listen(process.env.PORT, function () { console.log("Express server listening with https on port %d in %s mode", this.address().port, app.settings.env); }); }; if (process.env.NODE_ENV == 'production') { app.use(function (req, res, next) { res.setHeader('Strict-Transport-Security', 'max-age=8640000; includeSubDomains'); if (req.headers['x-forwarded-proto'] && req.headers['x-forwarded-proto'] === "http") { return res.redirect(301, 'https://' + req.host + req.url); } else { return next(); } }); } else { app.use(function (req, res, next) { res.setHeader('Strict-Transport-Security', 'max-age=8640000; includeSubDomains'); if (!req.secure) { return res.redirect(301, 'https://' + req.host + ":" + process.env.PORT + req.url); } else { return next(); } }); }; 

Bueno, la comunidad se ve bastante muerta en estos días (espero que me equivoque)

La respuesta es:

a) si, esta es la manera de lidiar con eso

b) la forma de comprobar si está en modo seguro o no depende también del entorno:

 if process.env.NODE_ENV == 'production' is_secure = (req) -> req.headers['x-forwarded-proto'] == 'https' else is_secure = (req) -> req.secure 

AGREGAR Si desea forzar HTTPS:

 redirect_to_https = (req, res, next) -> if not is_secure(req) res.redirect config.SECURE_DOMAIN + req.url else next() app .use(redirect_to_https) 

Puede usar app.enable('trust proxy') , luego req.secure boolean (http / https) funciona también en Heroku, o detrás de cualquier proxy de terminación SSL compatible.