Ответ 1
Вам не нужно слушать один и тот же порт, если вы следуете за соглашением
По соглашению при запросе http://127.0.0.1
ваш браузер попытается подключиться к порту 80. Если вы попытаетесь открыть https://127.0.0.1
, ваш браузер попытается подключиться к порту 443. Таким образом, чтобы обеспечить весь трафик, просто слушать к порту 80 на http с переадресацией на https, где у нас уже есть слушатель для https для порта 443. Здесь код:
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);
Тест с https:
$ curl https://127.0.0.1 -k
secure!
С 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
Если вы должны прослушивать один и тот же порт
Существует не простой способ прослушивания HTTP/https на одном и том же порту. Лучше всего создать прокси-сервер в простом сетевом сокете, который подключается к (http или https) в зависимости от характера входящего соединения (http против https).
Вот полный код (на основе https://gist.github.com/bnoordhuis/4740141), который делает именно это. Он прослушивает localhost: 3000 и передает его на http (который, в свою очередь, перенаправляет его на https), или если входящее соединение находится в https, оно просто передает его https-обработчику
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');
}
В качестве теста, если вы подключите его с помощью https, вы получите обработчик https:
$ curl https://127.0.0.1:3000 -k
HTTPS
если вы подключаете его с http, вы получаете обработчик перенаправления (который просто переносит вас на 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