Skip to content

Serve http and https and http2 connections over the same port with node.js,and add typescript support

License

Notifications You must be signed in to change notification settings

masx200/http-https-http2-polyglot

Repository files navigation

Description

说明

Serve http and https and http2 connections over the same port with node.js,

and add "typescript" support。

Thanks to the original author,

使用 node.js 在同一端口上服务 http 和 https 以及 http2 连接,

优化和重构,

并添加"TYPESCRIPT"支持。

多亏了原作者,

https://github.com/mscdex/httpolyglot

https://github.com/httptoolkit/httpolyglot

Requirements

要求

node.js -- v12.0.0 or newer

Install

安装

yarn add @masx200/http-https-http2-polyglot

Connection protocol judgment

连接协议判断

确定连接是否通过 tls。

Determine if the connection is over tls.

const istls = true === req.socket["encrypted"];

Determine if the connection is http/2.

确定连接是否为“ http / 2”。

const ishttp2 = "h2" === req.socket.alpnProtocol;

Examples

例子

http2 服务器推送

http2 server push

https://github.com/masx200/http-https-http2-polyglot/blob/master/test/push.js

import { createServer } from "../dist/index.js";
import { cert, key } from "./key-cert.js";
const port = 9002;
const server = createServer({ key, cert }, async (req, res) => {
    if (req.url == "/main.js") {
        res.statusCode = 200;
        res.setHeader("content-type", "application/javascript");
        res.end('alert("not from push stream")');
        return;
    } else {
        res.writeHead(200, { "Content-Type": "text/html" });
        if ("function" === typeof res["createPushResponse"]) {
            res.createPushResponse(
                { ":method": "GET", ":path": "/main.js" },
                (err, stream) => {
                    if (err) {
                        console.error(err);
                    } else {
                        stream.setHeader(
                            "content-type",
                            "application/javascript"
                        );
                        stream.end('alert("hello from push stream!");');
                    }
                }
            );
        }
        res.end('push<script src="/main.js"></script>');
    }
});
server.listen(port, "localhost", function () {
    console.log("httpolyglot server listening on port " + port);
});

Websocket server

Websocket 服务器

https://github.com/masx200/http-https-http2-polyglot/blob/master/test/websocket.js

import fs from "fs";
import path, { dirname } from "path";
import { fileURLToPath } from "url";
import ws from "ws";
import { createServer } from "../dist/index.js";
import { cert, key } from "./key-cert.js";
const port = 8999;
const wsServer = new ws.Server({ noServer: true });
wsServer.on("connection", (websocket, req) => {
    websocket.on("error", () => {});
    websocket.send(JSON.stringify(req.headers));
    websocket.send(
        (true === req.socket["encrypted"] ? "HTTPS" : "HTTP") + " Connection!"
    );
});
// @ts-ignore
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const server = createServer(
    {
        key,
        cert,
    },
    async function (req, res) {
        if (req.url === "/") {
            res.writeHead(200, { "Content-Type": "text/html" });

            res.end(
                "websocket<script type='module' src='./index.js'></script>"
            );
        } else if (req.url === "/index.js") {
            res.writeHead(200, { "Content-Type": "text/javascript" });
            const jsfile = await fs.promises.readFile(
                path.join(__dirname, "index.js")
            );
            res.write(jsfile);
            res.end();
        } else {
            res.statusCode = 404;
            res.write("404");
            res.end();
        }
    },
    function (req, socket, head) {
        wsServer.handleUpgrade(req, socket, head, function done(ws) {
            wsServer.emit("connection", ws, req);
        });
    }
);
//server.on("request", console.log);
//server.on("upgrade", console.log);
server.listen(port, "localhost", function () {
    console.log("httpolyglot server listening on port " + port);
});

Simple Determine the connection protocol

简单确定连接协议

import * as httpolyglot from "@masx200/http-https-http2-polyglot";
import fs from "fs";

const port = 9000;
const server = httpolyglot.createServer(
    {
        key: fs.readFileSync("server.key.pem"),
        cert: fs.readFileSync("server.crt.pem"),
    },
    function (req, res) {
        res.writeHead(200, { "Content-Type": "text/html" });
        res.end(
            (true === req.socket["encrypted"] ? "HTTPS" : "HTTP") +
                " Connection!"
        );
    }
);
server.listen(port, "localhost", function () {
    console.log("httpolyglot server listening on port " + port);
});

redirect all http connections to https:

将所有 http 连接重定向到 https

https://github.com/masx200/http-https-http2-polyglot/blob/master/test/redirect.js

import { createServer } from "../dist/index.js";
import { cert, key } from "./key-cert.js";
// @ts-ignore

const port = 9001;
const server = createServer(
    {
        key,
        cert,
    },
    function (req, res) {
        if (true === req.socket["encrypted"]) {
            res.writeHead(200, { "Content-Type": "text/html" });
            res.end("Welcome, HTTPS user!");
        } else {
            const host = req.headers["host"] || req.authority;
            const originurl = req.url || "";
            const tourl = new URL(originurl, "https://" + host);
            tourl.port = String(port);
            res.writeHead(302, {
                Location: tourl.href,
                "Content-Type": "text/html",
            });
            res.write("302");
            return res.end();
        }
    }
);

server.listen(port, "localhost", function () {
    console.log("httpolyglot server listening on port " + port);
});

create a "404 not found" server

创建“ 404 未找到”服务器

https://github.com/masx200/http-https-http2-polyglot/blob/master/test/notfound.js

import { createServer } from "../dist/index.js";
import { cert, key } from "./key-cert.js";
const port = 8998;
// @ts-ignore

const server = createServer({
    key,
    cert,
});

server.listen(port, "localhost", function () {
    console.log("httpolyglot server listening on port " + port);
});

API

Exports

https://github.com/masx200/http-https-http2-polyglot/blob/master/dist/index.d.ts

createServer - Creates and returns a new Server instance.

创建并返回一个新的 Server 实例。

declare function createServer(
    options: ServerOptions,
    requestListener?: RequestListener,
    upgradeListener?: UpgradeListener
): http2.Http2SecureServer & http.Server;

The requestListener is a function which is automatically added to the 'request' event

The upgradeListener is a function which is automatically added to the 'upgrade' event

If no "requestListener" or "upgradeListener" is provided, the default "404 not found" listener will be used instead.

Event "clientError", If a client connection emits an 'error' event, it will be forwarded here.

Event "tlsClientError", The 'tlsClientError' event is emitted when an error occurs before a secure connection is established.

Event: 'listening',Emitted when the server has been bound after calling server.listen().

Event: 'close', Emitted when the server closes

Event: 'error',Emitted when an error occurs on the server

Only "requestListener" will be called when the "request" event occurs.

Only "upgradeListener" will be called when the "upgrade" event occurs.

Do not add "request" or "upgrade" event listener because it is not recommended to add multiple event listeners for "request"or "upgrade".

requestListener是一个自动添加到'request'事件的函数

“ upgradeListener”是一个自动添加到“ upgrade”事件中的函数

如果未提供“ requestListener”或“ upgradeListener”,则将使用默认的“ 404 not found”监听器。

事件“ clientError”,如果客户端连接发出error事件,它将在此处转发。

事件“ tlsClientError”,在建立安全连接之前发生错误时,将发出“ tlsClientError”事件。

事件:'listening',在调用server.listen()后绑定服务器时触发。

事件:“ close”,在服务器关闭时发出

事件:error,在服务器上发生错误时发出

发生“ request”事件时,仅将调用“ requestListener”。

发生upgrade事件时,仅会调用“ upgradeListener”。

不要添加requestrequest事件侦听器,因为不建议为requestrequest添加多个事件侦听器。

How it Works

这个怎么运作

https://github.com/lvgithub/blog/blob/master/http_and_https_over_same_port/README.MD

TLS and HTTP connections are easy to distinguish based on the first byte sent by clients trying to connect. See this comment for more information.

TLS 和 HTTP 连接很容易根据尝试连接的客户端发送的第一个字节进行区分。有关更多信息,请参见此评论。

mscdex/httpolyglot#3 (comment)

https://github.com/httptoolkit/httpolyglot/blob/master/lib/index.js

test

测试

yarn install
yarn build
yarn generate
yarn serve
yarn test
yarn curl
yarn open

About

Serve http and https and http2 connections over the same port with node.js,and add typescript support

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published