Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 19 additions & 29 deletions bin/configurable-http-proxy
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import fs from "node:fs";
import { Command } from "commander";

import ConfigurableProxy from "../lib/configproxy.js";
import { parseListenOptions } from "../lib/configproxy.js";

import { defaultLogger } from "../lib/log.js";

import { createRequire } from "node:module";
Expand All @@ -21,6 +23,7 @@ cli
.version(pkg.version)
.option("--ip <ip-address>", "Public-facing IP of the proxy")
.option("--port <n> (defaults to 8000)", "Public-facing port of the proxy", parseInt)
.option("--socket <path>", "Path to a UNIX domain socket for the proxy to listen on. Alternative to specifying IP and port.")
.option("--ssl-key <keyfile>", "SSL key to use, if any")
.option("--ssl-cert <certfile>", "SSL certificate to use, if any")
.option("--ssl-ca <ca-file>", "SSL certificate authority, if any")
Expand All @@ -39,6 +42,7 @@ cli
"Inward-facing port for API requests (defaults to --port=value+1)",
parseInt
)
.option("--api-socket <path>", "Path to a UNIX domain socket for the API server to listen on. Alternative to specifying API IP and port.")
.option("--api-ssl-key <keyfile>", "SSL key to use, if any, for API requests")
.option("--api-ssl-cert <certfile>", "SSL certificate to use, if any, for API requests")
.option("--api-ssl-ca <ca-file>", "SSL certificate authority, if any, for API requests")
Expand Down Expand Up @@ -93,6 +97,7 @@ cli
.option("--host-routing", "Use host routing (host as first level of path)")
.option("--metrics-ip <ip>", "IP for metrics server", "")
.option("--metrics-port <n>", "Port of metrics server. Defaults to no metrics server")
.option("--metrics-socket <path>", "Path to a UNIX domain socket for the metrics server to listen on. Alternative to specifying metrics IP and port.")
.option("--log-level <loglevel>", "Log level (debug, info, warn, error)", "info")
.option(
"--timeout <n>",
Expand Down Expand Up @@ -279,7 +284,7 @@ options.proxyTimeout = args.proxyTimeout;
options.keepAliveTimeout = args.keepAliveTimeout;

// metrics options
options.enableMetrics = !!args.metricsPort;
options.enableMetrics = !!args.metricsPort || !!args.metricsSocket;

// certs need to be provided for https redirection
if (!options.ssl && options.redirectPort) {
Expand Down Expand Up @@ -320,42 +325,27 @@ options.storageBackend = args.storageBackend;

var proxy = new ConfigurableProxy(options);

var listen = {};
listen.port = parseInt(args.port) || 8000;
if (args.ip === "*") {
// handle ip=* alias for all interfaces
log.warn(
"Interpreting ip='*' as all-interfaces. Preferred usage is 0.0.0.0 for all IPv4 or '' for all-interfaces."
);
args.ip = "";
}
listen.ip = args.ip;
listen.apiIp = args.apiIp;
listen.apiPort = args.apiPort || listen.port + 1;
listen.metricsIp = args.metricsIp;
listen.metricsPort = args.metricsPort;

proxy.proxyServer.listen(listen.port, listen.ip);
proxy.apiServer.listen(listen.apiPort, listen.apiIp);
if (listen.metricsPort) {
proxy.metricsServer.listen(listen.metricsPort, listen.metricsIp);
var listen = parseListenOptions(args);

proxy.proxyServer.listen(...listen.proxyTarget);
proxy.apiServer.listen(...listen.apiTarget);
if (listen.metricsTarget) {
proxy.metricsServer.listen(...listen.metricsTarget);
}

log.info(
"Proxying %s://%s:%s to %s",
"Proxying %s://%s to %s",
options.ssl ? "https" : "http",
listen.ip || "*",
listen.port,
listen.proxyTarget.join(":"),
options.defaultTarget || "(no default)"
);
log.info(
"Proxy API at %s://%s:%s/api/routes",
"Proxy API at %s://%s/api/routes",
options.apiSsl ? "https" : "http",
listen.apiIp || "*",
listen.apiPort
listen.apiTarget.join(":")
);
if (listen.metricsPort) {
log.info("Serve metrics at %s://%s:%s/metrics", "http", listen.metricsIp, listen.metricsPort);
if (listen.metricsTarget) {
log.info("Serve metrics at %s://%s/metrics", "http", listen.metricsTarget.join(":"));
}

if (args.pidFile) {
Expand All @@ -370,7 +360,7 @@ if (args.pidFile) {
}

// Redirect HTTP to HTTPS on the proxy's port
if (options.redirectPort && listen.port !== 80) {
if (options.redirectPort && listen.port && listen.port !== 80) {
var http = require("http");
var redirectPort = options.redirectTo ? options.redirectTo : listen.port;
var server = http
Expand Down
42 changes: 42 additions & 0 deletions lib/configproxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,48 @@ const require = createRequire(import.meta.url);

const __dirname = path.dirname(fileURLToPath(import.meta.url));

export function parseListenOptions(args) {
var listen = {};

if (args.socket) {
listen.proxyTarget = [args.socket];
log.warn(
"Proxy will listen on UNIX domain socket, --ip and --port options will be ignored."
);
} else {
listen.port = parseInt(args.port) || 8000;
if (args.ip === "*") {
// handle ip=* alias for all interfaces
log.warn(
"Interpreting ip='*' as all-interfaces. Preferred usage is 0.0.0.0 for all IPv4 or '' for all-interfaces."
);
args.ip = "";
}
listen.ip = args.ip;
listen.proxyTarget = [listen.port, listen.ip];
}

if (args.apiSocket) {
listen.apiSocket = [args.apiSocket];
log.warn(
"API server will listen on UNIX domain socket, --api-ip and --api-port options will be ignored."
);
} else {
listen.apiPort = args.apiPort ? parseInt(args.apiPort) : (listen.port ? listen.port + 1 : 8001);
listen.apiTarget = [listen.apiPort, args.apiIp];
}

if (args.metricsSocket) {
listen.metricsSocket = [args.metricsSocket];
log.warn(
"Metrics server will listen on UNIX domain socket, --metrics-ip and --metrics-port options will be ignored."
);
} else if (args.metricsPort) {
listen.metricsTarget = [parseInt(args.metricsPort), args.metricsIp];
}
return listen;
}

function bound(that, method) {
// bind a method, to ensure `this=that` when it is called
// because prototype languages are bad
Expand Down
16 changes: 9 additions & 7 deletions lib/testutil.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import http from "node:http";
import https from "node:https";
import { WebSocketServer } from "ws";
import { ConfigurableProxy } from "./configproxy.js";
import { ConfigurableProxy, parseListenOptions } from "./configproxy.js";
import { defaultLogger } from "./log.js";

var servers = [];
Expand Down Expand Up @@ -87,14 +87,16 @@ export function addTargets(proxy, paths, port) {
});
}

export function setupProxy(port, options, paths) {
export function setupProxy(listenOptions, options, paths) {
options = options || {};
options.authToken = "secret";
options.log = defaultLogger({ level: "error" });

var listen = parseListenOptions(listenOptions);
var port = listen.port || 8000;
var ip = listen.ip;
var proxy = new ConfigurableProxy(options);
proxy._setup_timestamp = new Date(new Date().getTime() - 60000);
var ip = "127.0.0.1";

var countdown = 2;
var resolvePromise;

Expand Down Expand Up @@ -134,10 +136,10 @@ export function setupProxy(port, options, paths) {
proxy.proxyServer.on("listening", onlisten);

addTargets(proxy, paths || ["/"], port + 2).then(function () {
proxy.proxyServer.listen(port, ip);
proxy.apiServer.listen(port + 1, ip);
proxy.proxyServer.listen(...listen.proxyTarget);
proxy.apiServer.listen(...listen.apiTarget);
if (options.enableMetrics) {
proxy.metricsServer.listen(port + 3, ip);
proxy.metricsServer.listen(...listen.metricsTarget);
}
});
return p;
Expand Down
10 changes: 7 additions & 3 deletions test/api_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,19 @@ log.remove(log.transports.Console);

describe("API Tests", function () {
var port = 8902;
var apiPort = port + 1;
var listenOptions = {
port: port,
apiPort: 8903,
ip: '127.0.0.1'
};
var proxy;
var apiUrl = "http://127.0.0.1:" + apiPort + "/api/routes";
var apiUrl = "http://" + listenOptions.ip + ":" + listenOptions.apiPort + "/api/routes";

var r;

beforeEach(function (callback) {
util
.setupProxy(port)
.setupProxy(listenOptions)
.then(function (newProxy) {
proxy = newProxy;
})
Expand Down
Loading