node.js - principiantes - node js tutorial
Nodejs HTTP y HTTPS en el mismo puerto (4)
No necesita escuchar en el mismo puerto si sigue las convenciones
Por convención cuando solicita http://127.0.0.1
su navegador intentará conectarse al puerto 80. Si intenta abrir https://127.0.0.1
su navegador intentará conectarse al puerto 443. Por lo tanto, para asegurar todo el tráfico, es simplemente convencional escuchar el puerto 80 en http con un redireccionamiento a https donde ya tenemos un oyente para https para el puerto 443. Aquí está el código:
var https = require(''https'');
var fs = require(''fs'');
var options = {
key: fs.readFileSync(''./key.pem''),
cert: fs.readFileSync(''./cert.pem'')
};
https.createServer(options, function (req, res) {
res.end(''secure!'');
}).listen(443);
// Redirect from http port 80 to https
var http = require(''http'');
http.createServer(function (req, res) {
res.writeHead(301, { "Location": "https://" + req.headers[''host''] + req.url });
res.end();
}).listen(80);
Prueba con https:
$ curl https://127.0.0.1 -k
secure!
Con http:
$ curl http://127.0.0.1 -i
HTTP/1.1 301 Moved Permanently
Location: https://127.0.0.1/
Date: Sun, 01 Jun 2014 06:15:16 GMT
Connection: keep-alive
Transfer-Encoding: chunked
Si debes escuchar en el mismo puerto
No hay una forma simple de escuchar http / https en el mismo puerto. Lo mejor que puede hacer es crear un servidor proxy en un socket de red simple que se conecta a (http o https) según la naturaleza de la conexión entrante (http vs. https).
Aquí está el código completo (basado en https://gist.github.com/bnoordhuis/4740141 ) que hace exactamente eso. Escucha en localhost: 3000 y lo canaliza a http (que a su vez lo redirecciona a https) o si la conexión entrante está en https, simplemente lo pasa a https handler
var fs = require(''fs'');
var net = require(''net'');
var http = require(''http'');
var https = require(''https'');
var baseAddress = 3000;
var redirectAddress = 3001;
var httpsAddress = 3002;
var httpsOptions = {
key: fs.readFileSync(''./key.pem''),
cert: fs.readFileSync(''./cert.pem'')
};
net.createServer(tcpConnection).listen(baseAddress);
http.createServer(httpConnection).listen(redirectAddress);
https.createServer(httpsOptions, httpsConnection).listen(httpsAddress);
function tcpConnection(conn) {
conn.once(''data'', function (buf) {
// A TLS handshake record starts with byte 22.
var address = (buf[0] === 22) ? httpsAddress : redirectAddress;
var proxy = net.createConnection(address, function () {
proxy.write(buf);
conn.pipe(proxy).pipe(conn);
});
});
}
function httpConnection(req, res) {
var host = req.headers[''host''];
res.writeHead(301, { "Location": "https://" + host + req.url });
res.end();
}
function httpsConnection(req, res) {
res.writeHead(200, { ''Content-Length'': ''5'' });
res.end(''HTTPS'');
}
Como prueba, si lo conecta con https obtiene el controlador https:
$ curl https://127.0.0.1:3000 -k
HTTPS
si lo conectas con http, obtienes el controlador de redirección (que simplemente te lleva al controlador https):
$ curl http://127.0.0.1:3000 -i
HTTP/1.1 301 Moved Permanently
Location: https://127.0.0.1:3000/
Date: Sat, 31 May 2014 16:36:56 GMT
Connection: keep-alive
Transfer-Encoding: chunked
He estado buscando en Google y mirando aquí en stackoverflow, pero no puedo encontrar una respuesta que me guste ;-)
Tengo un servidor NodeJS que se ejecuta sobre HTTPS y el puerto 3001. Ahora me gustaría buscar todas las solicitudes HTTP entrantes en el puerto 3001 y redirigirlas a la misma URL pero a través de HTTPS.
Esto debe ser posible. ¿No es así?
¡Gracias!
Sé que es una pregunta antigua, pero solo la pongo como referencia para otra persona. La forma más fácil que encontré fue utilizar el módulo https://github.com/mscdex/httpolyglot . Parece hacer lo que dice con bastante fiabilidad
var httpolyglot = require(''httpolyglot'');
var server = httpolyglot.createServer(options,function(req,res) {
if (!req.socket.encrypted) {
// Redirect to https
res.writeHead(301, { "Location": "https://" + req.headers[''host''] + req.url });
res.end();
} else {
// The express app or any other compatible app
app.apply(app,arguments);
}
});
// Some port
server.listen(11000);
Si es puro módulo HTTP Node.JS entonces puedes probar esto:
if (!request.connection.encrypted) { // Check if the request is not HTTPS
response.writeHead(301, { // May be 302
Location: ''https://'' + YourHostName + '':3001'' + request.url
/* Here you can add some more headers */
});
response.end(); // End the response
} else {
// Behavior for HTTPS requests
}
Si servir HTTP y HTTPS en un solo puerto es un requisito absoluto, puede realizar un proxy de la solicitud directamente a la implementación de HTTP relevante, en lugar de conectar el socket a otro puerto.
httpx.js
''use strict'';
let net = require(''net'');
let http = require(''http'');
let https = require(''https'');
exports.createServer = (opts, handler) => {
let server = net.createServer(socket => {
socket.once(''data'', buffer => {
// Pause the socket
socket.pause();
// Determine if this is an HTTP(s) request
let byte = buffer[0];
let protocol;
if (byte === 22) {
protocol = ''https'';
} else if (32 < byte && byte < 127) {
protocol = ''http'';
}
let proxy = server[protocol];
if (proxy) {
// Push the buffer back onto the front of the data stream
socket.unshift(buffer);
// Emit the socket to the HTTP(s) server
proxy.emit(''connection'', socket);
}
// Resume the socket data stream
socket.resume();
});
});
server.http = http.createServer(handler);
server.https = https.createServer(opts, handler);
return server;
};
ejemplo.js
''use strict'';
let express = require(''express'');
let fs = require(''fs'');
let io = require(''socket.io'');
let httpx = require(''./httpx'');
let opts = {
key: fs.readFileSync(''./server.key''),
cert: fs.readFileSync(''./server.cert'')
};
let app = express();
app.use(express.static(''public''));
let server = httpx.createServer(opts, app);
let ws = io(server.http);
let wss = io(server.https);
server.listen(8080, () => console.log(''Server started''));