Как обслуживать оба протокола http и https в Node.js-приложениях без фреймворков?
Модуль http не поддерживает протокол HTTPS, точно так же, как модуль https не поддерживает HTTPS. Отсюда возникает сразу много проблем.
Например мы переносим сайт с HTTP на HTTPS или наоборот. Переписывать приложение? Но в данном вопросе хотел бы рассмотреть другую задачу. Допустим, мы обслуживаем запросы как с HTTP, так и HTTPS. На основе какой концепции нужно писать код, чтобы сервер мог обслуживать оба протокола?
На данный момент у меня рабочих идей нет. Типичный Hello, world для модуля HTTP выглядит как-то так:
import HTTP from "http";
HTTP.createServer(requestListener).listen(PORT, HOST, (): void => {
console.log({
title: "Сервер запущен",
description: `Ожидание запросов на хост:${HOST}, порт: ${PORT}...`
});
});
Чтобы добавить поддержку HTTPS, нужно прописать аналогичную конструкцию для модуля HTTPS и у нас будет-два сервер приложения? Хочется верить, что нет, но если это единственный путь без фреймворков, то я сделаю это.
Внимание: ещё раз повторю, что я не прошу рекомендовать никакие фреймворке типа Express. В данном вопросе рассматривается реализация данного функционала без фреймворков.
Ответы (1 шт):
Да, два сервиса это - единственный путь. А вот обработчик запросов у них может быть общий!
import fs from "fs";
import http from "http";
import https from "https";
const requestListener = (req: http.IncomingMessage, res: http.ServerResponse) => {
console.log(`incoming, ${req.url}`, req.headers);
res.writeHead(200);
res.end('Hello World!');
};
const server1 = http.createServer(requestListener);
const server2 = https.createServer(
{
key: fs.readFileSync('./localhost.key'),
cert: fs.readFileSync('./localhost.crt')
},
requestListener
);
server1.listen(3080, 'localhost',
() => console.log('HTTP server localhost:3080 was runing...'));
server2.listen(3443, 'localhost',
() => console.log('HTTPS server localhost:3443 was runing...'));
$ curl http://localhost:3080/
Hello World!
$ curl https://localhost:3443/
Hello World!
Инструкция как создать самоподписанный сертификат
Простейший способ добавить самоподписанный сертификат в доверенные на mac os x:
$ sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain localhost.crt
UPD, в комментариях был задан вопрос:
Подскажите пожалуйста, а это нормально, что
server2использует разработчик с параметрами типовhttp.IncomingMessageиhttp.ServerResponse? Эти типы вроде как дляhttp.
Тут всё просто - смотрим определения типов (type definitions).
Для модуля http объявлен тип RequestListener
type RequestListener = (req: IncomingMessage, res: ServerResponse) => void;
и сигнатура функции createServer
function createServer(requestListener?: RequestListener): Server;
function createServer(options: ServerOptions, requestListener?: RequestListener): Server;
А в модуле https
import * as http from 'http';
...
function createServer(requestListener?: http.RequestListener): Server;
function createServer(options: ServerOptions, requestListener?: http.RequestListener): Server;
Видно, что и для http, и для https аргумент requestListener имеет один и тот же тип - RequestListener.