change to route based approach
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import * as plugins from '../../plugins.js';
|
||||
|
||||
// Importing from the new structure
|
||||
// Importing required components
|
||||
import { ConnectionManager } from './connection-manager.js';
|
||||
import { SecurityManager } from './security-manager.js';
|
||||
import { DomainConfigManager } from './domain-config-manager.js';
|
||||
@@ -8,23 +8,27 @@ import { TlsManager } from './tls-manager.js';
|
||||
import { NetworkProxyBridge } from './network-proxy-bridge.js';
|
||||
import { TimeoutManager } from './timeout-manager.js';
|
||||
import { PortRangeManager } from './port-range-manager.js';
|
||||
import { ConnectionHandler } from './connection-handler.js';
|
||||
import { RouteManager } from './route-manager.js';
|
||||
import { RouteConnectionHandler } from './route-connection-handler.js';
|
||||
|
||||
// External dependencies from migrated modules
|
||||
// External dependencies
|
||||
import { Port80Handler } from '../../http/port80/port80-handler.js';
|
||||
import { CertProvisioner } from '../../certificate/providers/cert-provisioner.js';
|
||||
import type { ICertificateData } from '../../certificate/models/certificate-types.js';
|
||||
import { buildPort80Handler } from '../../certificate/acme/acme-factory.js';
|
||||
import type { TForwardingType } from '../../forwarding/config/forwarding-types.js';
|
||||
import { createPort80HandlerOptions } from '../../common/port80-adapter.js';
|
||||
|
||||
// Import types from models
|
||||
import type { ISmartProxyOptions, IDomainConfig } from './models/interfaces.js';
|
||||
// Provide backward compatibility types
|
||||
export type { ISmartProxyOptions as IPortProxySettings, IDomainConfig };
|
||||
// Import types and utilities
|
||||
import type {
|
||||
ISmartProxyOptions,
|
||||
IRoutedSmartProxyOptions,
|
||||
IDomainConfig
|
||||
} from './models/interfaces.js';
|
||||
import { isRoutedOptions, isLegacyOptions } from './models/interfaces.js';
|
||||
import type { IRouteConfig } from './models/route-types.js';
|
||||
|
||||
/**
|
||||
* SmartProxy - Main class that coordinates all components
|
||||
* SmartProxy - Unified route-based API
|
||||
*/
|
||||
export class SmartProxy extends plugins.EventEmitter {
|
||||
private netServers: plugins.net.Server[] = [];
|
||||
@@ -34,24 +38,28 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
// Component managers
|
||||
private connectionManager: ConnectionManager;
|
||||
private securityManager: SecurityManager;
|
||||
public domainConfigManager: DomainConfigManager;
|
||||
private domainConfigManager: DomainConfigManager;
|
||||
private tlsManager: TlsManager;
|
||||
private networkProxyBridge: NetworkProxyBridge;
|
||||
private timeoutManager: TimeoutManager;
|
||||
private portRangeManager: PortRangeManager;
|
||||
private connectionHandler: ConnectionHandler;
|
||||
private routeManager: RouteManager;
|
||||
private routeConnectionHandler: RouteConnectionHandler;
|
||||
|
||||
// Port80Handler for ACME certificate management
|
||||
private port80Handler: Port80Handler | null = null;
|
||||
// CertProvisioner for unified certificate workflows
|
||||
private certProvisioner?: CertProvisioner;
|
||||
|
||||
/**
|
||||
* Constructor that supports both legacy and route-based configuration
|
||||
*/
|
||||
constructor(settingsArg: ISmartProxyOptions) {
|
||||
super();
|
||||
|
||||
// Set reasonable defaults for all settings
|
||||
this.settings = {
|
||||
...settingsArg,
|
||||
targetIP: settingsArg.targetIP || 'localhost',
|
||||
initialDataTimeout: settingsArg.initialDataTimeout || 120000,
|
||||
socketTimeout: settingsArg.socketTimeout || 3600000,
|
||||
inactivityCheckInterval: settingsArg.inactivityCheckInterval || 60000,
|
||||
@@ -76,12 +84,11 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
keepAliveInactivityMultiplier: settingsArg.keepAliveInactivityMultiplier || 6,
|
||||
extendedKeepAliveLifetime: settingsArg.extendedKeepAliveLifetime || 7 * 24 * 60 * 60 * 1000,
|
||||
networkProxyPort: settingsArg.networkProxyPort || 8443,
|
||||
acme: settingsArg.acme || {},
|
||||
globalPortRanges: settingsArg.globalPortRanges || [],
|
||||
};
|
||||
|
||||
// Set default ACME options if not provided
|
||||
if (!this.settings.acme || Object.keys(this.settings.acme).length === 0) {
|
||||
this.settings.acme = this.settings.acme || {};
|
||||
if (Object.keys(this.settings.acme).length === 0) {
|
||||
this.settings.acme = {
|
||||
enabled: false,
|
||||
port: 80,
|
||||
@@ -91,7 +98,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
autoRenew: true,
|
||||
certificateStore: './certs',
|
||||
skipConfiguredCerts: false,
|
||||
httpsRedirectPort: this.settings.fromPort,
|
||||
httpsRedirectPort: this.settings.fromPort || 443,
|
||||
renewCheckIntervalHours: 24,
|
||||
domainForwards: []
|
||||
};
|
||||
@@ -105,13 +112,20 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
this.securityManager,
|
||||
this.timeoutManager
|
||||
);
|
||||
|
||||
// Create domain config manager and port range manager (for backward compatibility)
|
||||
this.domainConfigManager = new DomainConfigManager(this.settings);
|
||||
this.tlsManager = new TlsManager(this.settings);
|
||||
this.networkProxyBridge = new NetworkProxyBridge(this.settings);
|
||||
this.portRangeManager = new PortRangeManager(this.settings);
|
||||
|
||||
// Initialize connection handler
|
||||
this.connectionHandler = new ConnectionHandler(
|
||||
// Create the new route manager
|
||||
this.routeManager = new RouteManager(this.settings);
|
||||
|
||||
// Create other required components
|
||||
this.tlsManager = new TlsManager(this.settings);
|
||||
this.networkProxyBridge = new NetworkProxyBridge(this.settings);
|
||||
|
||||
// Initialize connection handler with route support
|
||||
this.routeConnectionHandler = new RouteConnectionHandler(
|
||||
this.settings,
|
||||
this.connectionManager,
|
||||
this.securityManager,
|
||||
@@ -119,12 +133,12 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
this.tlsManager,
|
||||
this.networkProxyBridge,
|
||||
this.timeoutManager,
|
||||
this.portRangeManager
|
||||
this.routeManager
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The settings for the port proxy
|
||||
* The settings for the SmartProxy
|
||||
*/
|
||||
public settings: ISmartProxyOptions;
|
||||
|
||||
@@ -142,8 +156,9 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
// Build and start the Port80Handler
|
||||
this.port80Handler = buildPort80Handler({
|
||||
...config,
|
||||
httpsRedirectPort: config.httpsRedirectPort || this.settings.fromPort
|
||||
httpsRedirectPort: config.httpsRedirectPort || (isLegacyOptions(this.settings) ? this.settings.fromPort : 443)
|
||||
});
|
||||
|
||||
// Share Port80Handler with NetworkProxyBridge before start
|
||||
this.networkProxyBridge.setPort80Handler(this.port80Handler);
|
||||
await this.port80Handler.start();
|
||||
@@ -154,7 +169,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the proxy server
|
||||
* Start the proxy server with support for both configuration types
|
||||
*/
|
||||
public async start() {
|
||||
// Don't start if already shutting down
|
||||
@@ -163,11 +178,11 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process domain configs
|
||||
// Note: ensureForwardingConfig is no longer needed since forwarding is now required
|
||||
|
||||
// Initialize domain config manager with the processed configs
|
||||
this.domainConfigManager.updateDomainConfigs(this.settings.domainConfigs);
|
||||
// If using legacy format, make sure domainConfigs are initialized
|
||||
if (isLegacyOptions(this.settings)) {
|
||||
// Initialize domain config manager with the processed configs
|
||||
this.domainConfigManager.updateDomainConfigs(this.settings.domainConfigs);
|
||||
}
|
||||
|
||||
// Initialize Port80Handler if enabled
|
||||
await this.initializePort80Handler();
|
||||
@@ -176,20 +191,39 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
if (this.port80Handler) {
|
||||
const acme = this.settings.acme!;
|
||||
|
||||
// Convert domain forwards to use the new forwarding system if possible
|
||||
// Setup domain forwards based on configuration type
|
||||
const domainForwards = acme.domainForwards?.map(f => {
|
||||
// If the domain has a forwarding config in domainConfigs, use that
|
||||
const domainConfig = this.settings.domainConfigs.find(
|
||||
dc => dc.domains.some(d => d === f.domain)
|
||||
);
|
||||
if (isLegacyOptions(this.settings)) {
|
||||
// If using legacy mode, check if domain config exists
|
||||
const domainConfig = this.settings.domainConfigs.find(
|
||||
dc => dc.domains.some(d => d === f.domain)
|
||||
);
|
||||
|
||||
if (domainConfig?.forwarding) {
|
||||
return {
|
||||
if (domainConfig?.forwarding) {
|
||||
return {
|
||||
domain: f.domain,
|
||||
forwardConfig: f.forwardConfig,
|
||||
acmeForwardConfig: f.acmeForwardConfig,
|
||||
sslRedirect: f.sslRedirect || domainConfig.forwarding.http?.redirectToHttps || false
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// In route mode, look for matching route
|
||||
const route = this.routeManager.findMatchingRoute({
|
||||
port: 443,
|
||||
domain: f.domain,
|
||||
forwardConfig: f.forwardConfig,
|
||||
acmeForwardConfig: f.acmeForwardConfig,
|
||||
sslRedirect: f.sslRedirect || domainConfig.forwarding.http?.redirectToHttps || false
|
||||
};
|
||||
clientIp: '127.0.0.1' // Dummy IP for finding routes
|
||||
})?.route;
|
||||
|
||||
if (route && route.action.type === 'forward' && route.action.tls) {
|
||||
// If we found a matching route with TLS settings
|
||||
return {
|
||||
domain: f.domain,
|
||||
forwardConfig: f.forwardConfig,
|
||||
acmeForwardConfig: f.acmeForwardConfig,
|
||||
sslRedirect: f.sslRedirect || false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise use the existing configuration
|
||||
@@ -201,17 +235,38 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
};
|
||||
}) || [];
|
||||
|
||||
this.certProvisioner = new CertProvisioner(
|
||||
this.settings.domainConfigs,
|
||||
this.port80Handler,
|
||||
this.networkProxyBridge,
|
||||
this.settings.certProvisionFunction,
|
||||
acme.renewThresholdDays!,
|
||||
acme.renewCheckIntervalHours!,
|
||||
acme.autoRenew!,
|
||||
domainForwards
|
||||
);
|
||||
// Create CertProvisioner with appropriate parameters
|
||||
if (isLegacyOptions(this.settings)) {
|
||||
this.certProvisioner = new CertProvisioner(
|
||||
this.settings.domainConfigs,
|
||||
this.port80Handler,
|
||||
this.networkProxyBridge,
|
||||
this.settings.certProvisionFunction,
|
||||
acme.renewThresholdDays!,
|
||||
acme.renewCheckIntervalHours!,
|
||||
acme.autoRenew!,
|
||||
domainForwards
|
||||
);
|
||||
} else {
|
||||
// For route-based configuration, we need to adapt the interface
|
||||
// Convert routes to domain configs for CertProvisioner
|
||||
const domainConfigs: IDomainConfig[] = this.extractDomainConfigsFromRoutes(
|
||||
(this.settings as IRoutedSmartProxyOptions).routes
|
||||
);
|
||||
|
||||
this.certProvisioner = new CertProvisioner(
|
||||
domainConfigs,
|
||||
this.port80Handler,
|
||||
this.networkProxyBridge,
|
||||
this.settings.certProvisionFunction,
|
||||
acme.renewThresholdDays!,
|
||||
acme.renewCheckIntervalHours!,
|
||||
acme.autoRenew!,
|
||||
domainForwards
|
||||
);
|
||||
}
|
||||
|
||||
// Register certificate event handler
|
||||
this.certProvisioner.on('certificate', (certData) => {
|
||||
this.emit('certificate', {
|
||||
domain: certData.domain,
|
||||
@@ -228,25 +283,22 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
}
|
||||
|
||||
// Initialize and start NetworkProxy if needed
|
||||
if (
|
||||
this.settings.useNetworkProxy &&
|
||||
this.settings.useNetworkProxy.length > 0
|
||||
) {
|
||||
if (this.settings.useNetworkProxy && this.settings.useNetworkProxy.length > 0) {
|
||||
await this.networkProxyBridge.initialize();
|
||||
await this.networkProxyBridge.start();
|
||||
}
|
||||
|
||||
// Validate port configuration
|
||||
const configWarnings = this.portRangeManager.validateConfiguration();
|
||||
// Validate the route configuration
|
||||
const configWarnings = this.routeManager.validateConfiguration();
|
||||
if (configWarnings.length > 0) {
|
||||
console.log("Port configuration warnings:");
|
||||
console.log("Route configuration warnings:");
|
||||
for (const warning of configWarnings) {
|
||||
console.log(` - ${warning}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Get listening ports from PortRangeManager
|
||||
const listeningPorts = this.portRangeManager.getListeningPorts();
|
||||
// Get listening ports from RouteManager
|
||||
const listeningPorts = this.routeManager.getListeningPorts();
|
||||
|
||||
// Create servers for each port
|
||||
for (const port of listeningPorts) {
|
||||
@@ -258,8 +310,8 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
return;
|
||||
}
|
||||
|
||||
// Delegate to connection handler
|
||||
this.connectionHandler.handleConnection(socket);
|
||||
// Delegate to route connection handler
|
||||
this.routeConnectionHandler.handleConnection(socket);
|
||||
}).on('error', (err: Error) => {
|
||||
console.log(`Server Error on port ${port}: ${err.message}`);
|
||||
});
|
||||
@@ -268,7 +320,9 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
const isNetworkProxyPort = this.settings.useNetworkProxy?.includes(port);
|
||||
console.log(
|
||||
`SmartProxy -> OK: Now listening on port ${port}${
|
||||
this.settings.sniEnabled && !isNetworkProxyPort ? ' (SNI passthrough enabled)' : ''
|
||||
isLegacyOptions(this.settings) && this.settings.sniEnabled && !isNetworkProxyPort ?
|
||||
' (SNI passthrough enabled)' :
|
||||
''
|
||||
}${isNetworkProxyPort ? ' (NetworkProxy forwarding enabled)' : ''}`
|
||||
);
|
||||
});
|
||||
@@ -348,12 +402,70 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract domain configurations from routes for certificate provisioning
|
||||
*/
|
||||
private extractDomainConfigsFromRoutes(routes: IRouteConfig[]): IDomainConfig[] {
|
||||
const domainConfigs: IDomainConfig[] = [];
|
||||
|
||||
for (const route of routes) {
|
||||
// Skip routes without domain specs
|
||||
if (!route.match.domains) continue;
|
||||
|
||||
// Skip non-forward routes
|
||||
if (route.action.type !== 'forward') continue;
|
||||
|
||||
// Only process routes that need TLS termination (those with certificates)
|
||||
if (!route.action.tls ||
|
||||
route.action.tls.mode === 'passthrough' ||
|
||||
!route.action.target) continue;
|
||||
|
||||
const domains = Array.isArray(route.match.domains)
|
||||
? route.match.domains
|
||||
: [route.match.domains];
|
||||
|
||||
// Determine forwarding type based on TLS mode
|
||||
const forwardingType = route.action.tls.mode === 'terminate'
|
||||
? 'https-terminate-to-http'
|
||||
: 'https-terminate-to-https';
|
||||
|
||||
// Create a forwarding config
|
||||
const forwarding = {
|
||||
type: forwardingType as any,
|
||||
target: {
|
||||
host: Array.isArray(route.action.target.host)
|
||||
? route.action.target.host[0]
|
||||
: route.action.target.host,
|
||||
port: route.action.target.port
|
||||
},
|
||||
// Add TLS settings
|
||||
https: {
|
||||
customCert: route.action.tls.certificate !== 'auto'
|
||||
? route.action.tls.certificate
|
||||
: undefined
|
||||
},
|
||||
// Add security settings if present
|
||||
security: route.action.security,
|
||||
// Add advanced settings if present
|
||||
advanced: route.action.advanced
|
||||
};
|
||||
|
||||
domainConfigs.push({
|
||||
domains,
|
||||
forwarding
|
||||
});
|
||||
}
|
||||
|
||||
return domainConfigs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the proxy server
|
||||
*/
|
||||
public async stop() {
|
||||
console.log('SmartProxy shutting down...');
|
||||
this.isShuttingDown = true;
|
||||
|
||||
// Stop CertProvisioner if active
|
||||
if (this.certProvisioner) {
|
||||
await this.certProvisioner.stop();
|
||||
@@ -411,14 +523,17 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the domain configurations for the proxy
|
||||
* Updates the domain configurations for the proxy (legacy support)
|
||||
*/
|
||||
public async updateDomainConfigs(newDomainConfigs: IDomainConfig[]): Promise<void> {
|
||||
console.log(`Updating domain configurations (${newDomainConfigs.length} configs)`);
|
||||
|
||||
// Update domain configs in DomainConfigManager
|
||||
// Update domain configs in DomainConfigManager (legacy)
|
||||
this.domainConfigManager.updateDomainConfigs(newDomainConfigs);
|
||||
|
||||
// Also update the RouteManager with these domain configs
|
||||
this.routeManager.updateFromDomainConfigs(newDomainConfigs);
|
||||
|
||||
// If NetworkProxy is initialized, resync the configurations
|
||||
if (this.networkProxyBridge.getNetworkProxy()) {
|
||||
await this.networkProxyBridge.syncDomainConfigsToNetworkProxy();
|
||||
@@ -428,7 +543,7 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
if (this.port80Handler && this.settings.acme?.enabled) {
|
||||
for (const domainConfig of newDomainConfigs) {
|
||||
// Skip certificate provisioning for http-only or passthrough configs that don't need certs
|
||||
const forwardingType = domainConfig.forwarding.type;
|
||||
const forwardingType = this.domainConfigManager.getForwardingType(domainConfig);
|
||||
const needsCertificate =
|
||||
forwardingType === 'https-terminate-to-http' ||
|
||||
forwardingType === 'https-terminate-to-https';
|
||||
@@ -490,6 +605,95 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update routes with new configuration (new API)
|
||||
*/
|
||||
public async updateRoutes(newRoutes: IRouteConfig[]): Promise<void> {
|
||||
console.log(`Updating routes (${newRoutes.length} routes)`);
|
||||
|
||||
// Update routes in RouteManager
|
||||
this.routeManager.updateRoutes(newRoutes);
|
||||
|
||||
// If NetworkProxy is initialized, resync the configurations
|
||||
if (this.networkProxyBridge.getNetworkProxy()) {
|
||||
// Create equivalent domain configs for NetworkProxy
|
||||
const domainConfigs = this.extractDomainConfigsFromRoutes(newRoutes);
|
||||
|
||||
// Update domain configs in DomainConfigManager for sync
|
||||
this.domainConfigManager.updateDomainConfigs(domainConfigs);
|
||||
|
||||
// Sync with NetworkProxy
|
||||
await this.networkProxyBridge.syncDomainConfigsToNetworkProxy();
|
||||
}
|
||||
|
||||
// If Port80Handler is running, provision certificates based on routes
|
||||
if (this.port80Handler && this.settings.acme?.enabled) {
|
||||
for (const route of newRoutes) {
|
||||
// Skip routes without domains
|
||||
if (!route.match.domains) continue;
|
||||
|
||||
// Skip non-forward routes
|
||||
if (route.action.type !== 'forward') continue;
|
||||
|
||||
// Skip routes without TLS termination
|
||||
if (!route.action.tls ||
|
||||
route.action.tls.mode === 'passthrough' ||
|
||||
!route.action.target) continue;
|
||||
|
||||
// Skip certificate provisioning if certificate is not auto
|
||||
if (route.action.tls.certificate !== 'auto') continue;
|
||||
|
||||
const domains = Array.isArray(route.match.domains)
|
||||
? route.match.domains
|
||||
: [route.match.domains];
|
||||
|
||||
for (const domain of domains) {
|
||||
const isWildcard = domain.includes('*');
|
||||
let provision: string | plugins.tsclass.network.ICert = 'http01';
|
||||
|
||||
if (this.settings.certProvisionFunction) {
|
||||
try {
|
||||
provision = await this.settings.certProvisionFunction(domain);
|
||||
} catch (err) {
|
||||
console.log(`certProvider error for ${domain}: ${err}`);
|
||||
}
|
||||
} else if (isWildcard) {
|
||||
console.warn(`Skipping wildcard domain without certProvisionFunction: ${domain}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (provision === 'http01') {
|
||||
if (isWildcard) {
|
||||
console.warn(`Skipping HTTP-01 for wildcard domain: ${domain}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Register domain with Port80Handler
|
||||
this.port80Handler.addDomain({
|
||||
domainName: domain,
|
||||
sslRedirect: true,
|
||||
acmeMaintenance: true
|
||||
});
|
||||
|
||||
console.log(`Registered domain ${domain} with Port80Handler for HTTP-01`);
|
||||
} else {
|
||||
// Handle static certificate (e.g., DNS-01 provisioned)
|
||||
const certObj = provision as plugins.tsclass.network.ICert;
|
||||
const certData: ICertificateData = {
|
||||
domain: certObj.domainName,
|
||||
certificate: certObj.publicKey,
|
||||
privateKey: certObj.privateKey,
|
||||
expiryDate: new Date(certObj.validUntil)
|
||||
};
|
||||
this.networkProxyBridge.applyExternalCertificate(certData);
|
||||
console.log(`Applied static certificate for ${domain} from certProvider`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Provisioned certificates for new routes');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a certificate for a specific domain
|
||||
@@ -583,7 +787,8 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
networkProxyConnections,
|
||||
terminationStats,
|
||||
acmeEnabled: !!this.port80Handler,
|
||||
port80HandlerPort: this.port80Handler ? this.settings.acme?.port : null
|
||||
port80HandlerPort: this.port80Handler ? this.settings.acme?.port : null,
|
||||
routes: this.routeManager.getListeningPorts().length
|
||||
};
|
||||
}
|
||||
|
||||
@@ -591,18 +796,44 @@ export class SmartProxy extends plugins.EventEmitter {
|
||||
* Get a list of eligible domains for ACME certificates
|
||||
*/
|
||||
public getEligibleDomainsForCertificates(): string[] {
|
||||
// Collect all non-wildcard domains from domain configs
|
||||
const domains: string[] = [];
|
||||
|
||||
for (const config of this.settings.domainConfigs) {
|
||||
// Get domains from routes
|
||||
const routes = isRoutedOptions(this.settings) ? this.settings.routes : [];
|
||||
|
||||
for (const route of routes) {
|
||||
if (!route.match.domains) continue;
|
||||
|
||||
// Skip routes without TLS termination or auto certificates
|
||||
if (route.action.type !== 'forward' ||
|
||||
!route.action.tls ||
|
||||
route.action.tls.mode === 'passthrough' ||
|
||||
route.action.tls.certificate !== 'auto') continue;
|
||||
|
||||
const routeDomains = Array.isArray(route.match.domains)
|
||||
? route.match.domains
|
||||
: [route.match.domains];
|
||||
|
||||
// Skip domains that can't be used with ACME
|
||||
const eligibleDomains = config.domains.filter(domain =>
|
||||
const eligibleDomains = routeDomains.filter(domain =>
|
||||
!domain.includes('*') && this.isValidDomain(domain)
|
||||
);
|
||||
|
||||
domains.push(...eligibleDomains);
|
||||
}
|
||||
|
||||
// For legacy mode, also get domains from domain configs
|
||||
if (isLegacyOptions(this.settings)) {
|
||||
for (const config of this.settings.domainConfigs) {
|
||||
// Skip domains that can't be used with ACME
|
||||
const eligibleDomains = config.domains.filter(domain =>
|
||||
!domain.includes('*') && this.isValidDomain(domain)
|
||||
);
|
||||
|
||||
domains.push(...eligibleDomains);
|
||||
}
|
||||
}
|
||||
|
||||
return domains;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user