fix: disable HTTP keepAlive (Node 18 behavior) with a config toggle (#5519)

* implement disable keepalive, handle request-proxy and config logic

* Invert keep-alive boolean setting

* fix: clean-up server.js diff

* fix: boolean flag type

* feat: disable keep-alive by default

---------

Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
This commit is contained in:
DeathStalker471
2026-04-24 12:53:35 -07:00
committed by GitHub
parent 77cbcd8774
commit b1ef254f78
4 changed files with 22 additions and 3 deletions
+3
View File
@@ -41,6 +41,9 @@ port: 8000
# Interval in seconds to write a heartbeat file. Set to 0 to disable.
# This is used primarily for Docker healthchecks.
heartbeatInterval: 0
# Enable HTTP/HTTPS keep-alive globally.
# Disabling restores old Node 18 behavior, can help if ECONNRESET and other network errors occur.
enableKeepAlive: false
# -- SSL options --
ssl:
# Enable SSL/TLS encryption
+8
View File
@@ -31,6 +31,7 @@ import { initConfig } from './config-init.js';
* @property {string} keyPassphrase SSL private key passphrase
* @property {boolean} whitelistMode If enable whitelist mode
* @property {boolean} basicAuthMode If enable basic authentication
* @property {boolean} enableKeepAlive Enable HTTP/HTTPS keep-alive globally
* @property {boolean} requestProxyEnabled If enable outgoing request proxy
* @property {string} requestProxyUrl Request proxy URL
* @property {string[]} requestProxyBypass Request proxy bypass list
@@ -76,6 +77,7 @@ export class CommandLineParser {
keyPassphrase: '',
whitelistMode: true,
basicAuthMode: false,
enableKeepAlive: false,
requestProxyEnabled: false,
requestProxyUrl: '',
requestProxyBypass: [],
@@ -217,6 +219,11 @@ export class CommandLineParser {
default: null,
describe: 'Enables basic authentication',
})
.option('enableKeepAlive', {
type: 'boolean',
default: null,
describe: 'Enable HTTP/HTTPS keep-alive globally',
})
.option('requestProxyEnabled', {
type: 'boolean',
default: null,
@@ -313,6 +320,7 @@ export class CommandLineParser {
keyPassphrase: cliArguments.keyPassphrase ?? getConfigValue('ssl.keyPassphrase', defaultConfig.keyPassphrase),
whitelistMode: cliArguments.whitelist ?? getConfigValue('whitelistMode', defaultConfig.whitelistMode, 'boolean'),
basicAuthMode: cliArguments.basicAuthMode ?? getConfigValue('basicAuthMode', defaultConfig.basicAuthMode, 'boolean'),
enableKeepAlive: cliArguments.enableKeepAlive ?? getConfigValue('enableKeepAlive', defaultConfig.enableKeepAlive, 'boolean'),
requestProxyEnabled: cliArguments.requestProxyEnabled ?? getConfigValue('requestProxy.enabled', defaultConfig.requestProxyEnabled, 'boolean'),
requestProxyUrl: cliArguments.requestProxyUrl ?? getConfigValue('requestProxy.url', defaultConfig.requestProxyUrl),
requestProxyBypass: cliArguments.requestProxyBypass ?? getConfigValue('requestProxy.bypass', defaultConfig.requestProxyBypass),
+4 -2
View File
@@ -13,8 +13,9 @@ const LOG_HEADER = '[Request Proxy]';
* @property {boolean} enabled Whether proxy is enabled.
* @property {string} url Proxy URL.
* @property {string[]} bypass List of URLs to bypass proxy.
* @property {boolean} enableKeepAlive Enable HTTP/HTTPS keep-alive.
*/
export default function initRequestProxy({ enabled, url, bypass }) {
export default function initRequestProxy({ enabled, url, bypass, enableKeepAlive }) {
try {
// No proxy is enabled, so return
if (!enabled) {
@@ -39,7 +40,8 @@ export default function initRequestProxy({ enabled, url, bypass }) {
process.env.no_proxy = bypass.join(',');
}
const proxyAgent = new ProxyAgent();
const proxyAgentOptions = enableKeepAlive ? { keepAlive: true } : { keepAlive: false };
const proxyAgent = new ProxyAgent(proxyAgentOptions);
http.globalAgent = proxyAgent;
https.globalAgent = proxyAgent;
+7 -1
View File
@@ -5,6 +5,8 @@ import util from 'node:util';
import net from 'node:net';
import dns from 'node:dns';
import process from 'node:process';
import http from 'node:http';
import https from 'node:https';
import cors from 'cors';
import { csrfSync } from 'csrf-sync';
@@ -93,6 +95,10 @@ if (!cliArgs.enableIPv6 && !cliArgs.enableIPv4) {
process.exit(1);
}
// Set keep-alive preference for all HTTP/HTTPS requests.
http.globalAgent = new http.Agent({ keepAlive: cliArgs.enableKeepAlive });
https.globalAgent = new https.Agent({ keepAlive: cliArgs.enableKeepAlive });
const app = express();
app.use(helmet({
contentSecurityPolicy: false,
@@ -328,7 +334,7 @@ async function preSetupTasks() {
});
// Add request proxy.
initRequestProxy({ enabled: cliArgs.requestProxyEnabled, url: cliArgs.requestProxyUrl, bypass: cliArgs.requestProxyBypass });
initRequestProxy({ enabled: cliArgs.requestProxyEnabled, url: cliArgs.requestProxyUrl, bypass: cliArgs.requestProxyBypass, enableKeepAlive: cliArgs.enableKeepAlive });
// Wait for frontend libs to compile
await webpackMiddleware.runWebpackCompiler({ pruneCache: true });