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:
@@ -41,6 +41,9 @@ port: 8000
|
|||||||
# Interval in seconds to write a heartbeat file. Set to 0 to disable.
|
# Interval in seconds to write a heartbeat file. Set to 0 to disable.
|
||||||
# This is used primarily for Docker healthchecks.
|
# This is used primarily for Docker healthchecks.
|
||||||
heartbeatInterval: 0
|
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 options --
|
||||||
ssl:
|
ssl:
|
||||||
# Enable SSL/TLS encryption
|
# Enable SSL/TLS encryption
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import { initConfig } from './config-init.js';
|
|||||||
* @property {string} keyPassphrase SSL private key passphrase
|
* @property {string} keyPassphrase SSL private key passphrase
|
||||||
* @property {boolean} whitelistMode If enable whitelist mode
|
* @property {boolean} whitelistMode If enable whitelist mode
|
||||||
* @property {boolean} basicAuthMode If enable basic authentication
|
* @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 {boolean} requestProxyEnabled If enable outgoing request proxy
|
||||||
* @property {string} requestProxyUrl Request proxy URL
|
* @property {string} requestProxyUrl Request proxy URL
|
||||||
* @property {string[]} requestProxyBypass Request proxy bypass list
|
* @property {string[]} requestProxyBypass Request proxy bypass list
|
||||||
@@ -76,6 +77,7 @@ export class CommandLineParser {
|
|||||||
keyPassphrase: '',
|
keyPassphrase: '',
|
||||||
whitelistMode: true,
|
whitelistMode: true,
|
||||||
basicAuthMode: false,
|
basicAuthMode: false,
|
||||||
|
enableKeepAlive: false,
|
||||||
requestProxyEnabled: false,
|
requestProxyEnabled: false,
|
||||||
requestProxyUrl: '',
|
requestProxyUrl: '',
|
||||||
requestProxyBypass: [],
|
requestProxyBypass: [],
|
||||||
@@ -217,6 +219,11 @@ export class CommandLineParser {
|
|||||||
default: null,
|
default: null,
|
||||||
describe: 'Enables basic authentication',
|
describe: 'Enables basic authentication',
|
||||||
})
|
})
|
||||||
|
.option('enableKeepAlive', {
|
||||||
|
type: 'boolean',
|
||||||
|
default: null,
|
||||||
|
describe: 'Enable HTTP/HTTPS keep-alive globally',
|
||||||
|
})
|
||||||
.option('requestProxyEnabled', {
|
.option('requestProxyEnabled', {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
default: null,
|
default: null,
|
||||||
@@ -313,6 +320,7 @@ export class CommandLineParser {
|
|||||||
keyPassphrase: cliArguments.keyPassphrase ?? getConfigValue('ssl.keyPassphrase', defaultConfig.keyPassphrase),
|
keyPassphrase: cliArguments.keyPassphrase ?? getConfigValue('ssl.keyPassphrase', defaultConfig.keyPassphrase),
|
||||||
whitelistMode: cliArguments.whitelist ?? getConfigValue('whitelistMode', defaultConfig.whitelistMode, 'boolean'),
|
whitelistMode: cliArguments.whitelist ?? getConfigValue('whitelistMode', defaultConfig.whitelistMode, 'boolean'),
|
||||||
basicAuthMode: cliArguments.basicAuthMode ?? getConfigValue('basicAuthMode', defaultConfig.basicAuthMode, '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'),
|
requestProxyEnabled: cliArguments.requestProxyEnabled ?? getConfigValue('requestProxy.enabled', defaultConfig.requestProxyEnabled, 'boolean'),
|
||||||
requestProxyUrl: cliArguments.requestProxyUrl ?? getConfigValue('requestProxy.url', defaultConfig.requestProxyUrl),
|
requestProxyUrl: cliArguments.requestProxyUrl ?? getConfigValue('requestProxy.url', defaultConfig.requestProxyUrl),
|
||||||
requestProxyBypass: cliArguments.requestProxyBypass ?? getConfigValue('requestProxy.bypass', defaultConfig.requestProxyBypass),
|
requestProxyBypass: cliArguments.requestProxyBypass ?? getConfigValue('requestProxy.bypass', defaultConfig.requestProxyBypass),
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ const LOG_HEADER = '[Request Proxy]';
|
|||||||
* @property {boolean} enabled Whether proxy is enabled.
|
* @property {boolean} enabled Whether proxy is enabled.
|
||||||
* @property {string} url Proxy URL.
|
* @property {string} url Proxy URL.
|
||||||
* @property {string[]} bypass List of URLs to bypass proxy.
|
* @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 {
|
try {
|
||||||
// No proxy is enabled, so return
|
// No proxy is enabled, so return
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
@@ -39,7 +40,8 @@ export default function initRequestProxy({ enabled, url, bypass }) {
|
|||||||
process.env.no_proxy = bypass.join(',');
|
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;
|
http.globalAgent = proxyAgent;
|
||||||
https.globalAgent = proxyAgent;
|
https.globalAgent = proxyAgent;
|
||||||
|
|
||||||
|
|||||||
+7
-1
@@ -5,6 +5,8 @@ import util from 'node:util';
|
|||||||
import net from 'node:net';
|
import net from 'node:net';
|
||||||
import dns from 'node:dns';
|
import dns from 'node:dns';
|
||||||
import process from 'node:process';
|
import process from 'node:process';
|
||||||
|
import http from 'node:http';
|
||||||
|
import https from 'node:https';
|
||||||
|
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import { csrfSync } from 'csrf-sync';
|
import { csrfSync } from 'csrf-sync';
|
||||||
@@ -93,6 +95,10 @@ if (!cliArgs.enableIPv6 && !cliArgs.enableIPv4) {
|
|||||||
process.exit(1);
|
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();
|
const app = express();
|
||||||
app.use(helmet({
|
app.use(helmet({
|
||||||
contentSecurityPolicy: false,
|
contentSecurityPolicy: false,
|
||||||
@@ -328,7 +334,7 @@ async function preSetupTasks() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Add request proxy.
|
// 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
|
// Wait for frontend libs to compile
|
||||||
await webpackMiddleware.runWebpackCompiler({ pruneCache: true });
|
await webpackMiddleware.runWebpackCompiler({ pruneCache: true });
|
||||||
|
|||||||
Reference in New Issue
Block a user