api: cluster support

still missing synchronization for some structures
This commit is contained in:
jj 2024-10-31 22:59:06 +00:00
parent 2d6d406f48
commit 40d6a02b61
No known key found for this signature in database
6 changed files with 114 additions and 24 deletions

View file

@ -1,4 +1,5 @@
import cors from "cors";
import http from "node:http";
import rateLimit from "express-rate-limit";
import { setGlobalDispatcher, ProxyAgent } from "undici";
import { getCommit, getBranch, getRemote, getVersion } from "@imput/version-info";
@ -7,9 +8,9 @@ import jwt from "../security/jwt.js";
import stream from "../stream/stream.js";
import match from "../processing/match.js";
import { env } from "../config.js";
import { env, setTunnelPort } from "../config.js";
import { extract } from "../processing/url.js";
import { Bright, Cyan } from "../misc/console-text.js";
import { Green, Bright, Cyan } from "../misc/console-text.js";
import { generateHmac, generateSalt } from "../misc/crypto.js";
import { randomizeCiphers } from "../misc/randomize-ciphers.js";
import { verifyTurnstileToken } from "../security/turnstile.js";
@ -40,7 +41,7 @@ const fail = (res, code, context) => {
res.status(status).json(body);
}
export const runAPI = (express, app, __dirname) => {
export const runAPI = (express, app, __dirname, isPrimary = true) => {
const startTime = new Date();
const startTimestamp = startTime.getTime();
@ -288,7 +289,7 @@ export const runAPI = (express, app, __dirname) => {
return stream(res, streamInfo);
})
app.get('/itunnel', (req, res) => {
const itunnelHandler = (req, res) => {
if (!req.ip.endsWith('127.0.0.1')) {
return res.sendStatus(403);
}
@ -308,7 +309,9 @@ export const runAPI = (express, app, __dirname) => {
]);
return stream(res, { type: 'internal', ...streamInfo });
})
};
app.get('/itunnel', itunnelHandler);
app.get('/', (_, res) => {
res.type('json');
@ -339,21 +342,27 @@ export const runAPI = (express, app, __dirname) => {
setGlobalDispatcher(new ProxyAgent(env.externalProxy))
}
app.listen(env.apiPort, env.listenAddress, () => {
console.log(`\n` +
Bright(Cyan("cobalt ")) + Bright("API ^ω⁠^") + "\n" +
http.createServer(app).listen({
port: env.apiPort,
host: env.listenAddress,
reusePort: env.instanceCount > 1 || undefined
}, () => {
if (isPrimary) {
console.log(`\n` +
Bright(Cyan("cobalt ")) + Bright("API ^ω⁠^") + "\n" +
"~~~~~~\n" +
Bright("version: ") + version + "\n" +
Bright("commit: ") + git.commit + "\n" +
Bright("branch: ") + git.branch + "\n" +
Bright("remote: ") + git.remote + "\n" +
Bright("start time: ") + startTime.toUTCString() + "\n" +
"~~~~~~\n" +
"~~~~~~\n" +
Bright("version: ") + version + "\n" +
Bright("commit: ") + git.commit + "\n" +
Bright("branch: ") + git.branch + "\n" +
Bright("remote: ") + git.remote + "\n" +
Bright("start time: ") + startTime.toUTCString() + "\n" +
"~~~~~~\n" +
Bright("url: ") + Bright(Cyan(env.apiURL)) + "\n" +
Bright("port: ") + env.apiPort + "\n"
);
Bright("url: ") + Bright(Cyan(env.apiURL)) + "\n" +
Bright("port: ") + env.apiPort + "\n"
);
}
if (env.apiKeyURL) {
APIKeys.setup(env.apiKeyURL);
@ -362,5 +371,19 @@ export const runAPI = (express, app, __dirname) => {
if (env.cookiePath) {
Cookies.setup(env.cookiePath);
}
})
});
if (!isPrimary) {
const istreamer = express();
istreamer.get('/itunnel', itunnelHandler);
const server = istreamer.listen({
port: 0,
host: '127.0.0.1',
exclusive: true
}, () => {
const { port } = server.address();
console.log(`${Green('[✓]')} cobalt sub-instance running on 127.0.0.1:${port}`);
setTunnelPort(port);
});
}
}