156 lines
4.9 KiB
TypeScript
156 lines
4.9 KiB
TypeScript
import type { IForwardConfig } from '../config/forwarding-types.js';
|
|
import { ForwardingHandler } from '../handlers/base-handler.js';
|
|
import { HttpForwardingHandler } from '../handlers/http-handler.js';
|
|
import { HttpsPassthroughHandler } from '../handlers/https-passthrough-handler.js';
|
|
import { HttpsTerminateToHttpHandler } from '../handlers/https-terminate-to-http-handler.js';
|
|
import { HttpsTerminateToHttpsHandler } from '../handlers/https-terminate-to-https-handler.js';
|
|
|
|
/**
|
|
* Factory for creating forwarding handlers based on the configuration type
|
|
*/
|
|
export class ForwardingHandlerFactory {
|
|
/**
|
|
* Create a forwarding handler based on the configuration
|
|
* @param config The forwarding configuration
|
|
* @returns The appropriate forwarding handler
|
|
*/
|
|
public static createHandler(config: IForwardConfig): ForwardingHandler {
|
|
// Create the appropriate handler based on the forwarding type
|
|
switch (config.type) {
|
|
case 'http-only':
|
|
return new HttpForwardingHandler(config);
|
|
|
|
case 'https-passthrough':
|
|
return new HttpsPassthroughHandler(config);
|
|
|
|
case 'https-terminate-to-http':
|
|
return new HttpsTerminateToHttpHandler(config);
|
|
|
|
case 'https-terminate-to-https':
|
|
return new HttpsTerminateToHttpsHandler(config);
|
|
|
|
default:
|
|
// Type system should prevent this, but just in case:
|
|
throw new Error(`Unknown forwarding type: ${(config as any).type}`);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Apply default values to a forwarding configuration based on its type
|
|
* @param config The original forwarding configuration
|
|
* @returns A configuration with defaults applied
|
|
*/
|
|
public static applyDefaults(config: IForwardConfig): IForwardConfig {
|
|
// Create a deep copy of the configuration
|
|
const result: IForwardConfig = JSON.parse(JSON.stringify(config));
|
|
|
|
// Apply defaults based on forwarding type
|
|
switch (config.type) {
|
|
case 'http-only':
|
|
// Set defaults for HTTP-only mode
|
|
result.http = {
|
|
enabled: true,
|
|
...config.http
|
|
};
|
|
break;
|
|
|
|
case 'https-passthrough':
|
|
// Set defaults for HTTPS passthrough
|
|
result.https = {
|
|
forwardSni: true,
|
|
...config.https
|
|
};
|
|
// SNI forwarding doesn't do HTTP
|
|
result.http = {
|
|
enabled: false,
|
|
...config.http
|
|
};
|
|
break;
|
|
|
|
case 'https-terminate-to-http':
|
|
// Set defaults for HTTPS termination to HTTP
|
|
result.https = {
|
|
...config.https
|
|
};
|
|
// Support HTTP access by default in this mode
|
|
result.http = {
|
|
enabled: true,
|
|
redirectToHttps: true,
|
|
...config.http
|
|
};
|
|
// Enable ACME by default
|
|
result.acme = {
|
|
enabled: true,
|
|
maintenance: true,
|
|
...config.acme
|
|
};
|
|
break;
|
|
|
|
case 'https-terminate-to-https':
|
|
// Similar to terminate-to-http but with different target handling
|
|
result.https = {
|
|
...config.https
|
|
};
|
|
result.http = {
|
|
enabled: true,
|
|
redirectToHttps: true,
|
|
...config.http
|
|
};
|
|
result.acme = {
|
|
enabled: true,
|
|
maintenance: true,
|
|
...config.acme
|
|
};
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Validate a forwarding configuration
|
|
* @param config The configuration to validate
|
|
* @throws Error if the configuration is invalid
|
|
*/
|
|
public static validateConfig(config: IForwardConfig): void {
|
|
// Validate common properties
|
|
if (!config.target) {
|
|
throw new Error('Forwarding configuration must include a target');
|
|
}
|
|
|
|
if (!config.target.host || (Array.isArray(config.target.host) && config.target.host.length === 0)) {
|
|
throw new Error('Target must include a host or array of hosts');
|
|
}
|
|
|
|
if (!config.target.port || config.target.port <= 0 || config.target.port > 65535) {
|
|
throw new Error('Target must include a valid port (1-65535)');
|
|
}
|
|
|
|
// Type-specific validation
|
|
switch (config.type) {
|
|
case 'http-only':
|
|
// HTTP-only needs http.enabled to be true
|
|
if (config.http?.enabled === false) {
|
|
throw new Error('HTTP-only forwarding must have HTTP enabled');
|
|
}
|
|
break;
|
|
|
|
case 'https-passthrough':
|
|
// HTTPS passthrough doesn't support HTTP
|
|
if (config.http?.enabled === true) {
|
|
throw new Error('HTTPS passthrough does not support HTTP');
|
|
}
|
|
|
|
// HTTPS passthrough doesn't work with ACME
|
|
if (config.acme?.enabled === true) {
|
|
throw new Error('HTTPS passthrough does not support ACME');
|
|
}
|
|
break;
|
|
|
|
case 'https-terminate-to-http':
|
|
case 'https-terminate-to-https':
|
|
// These modes support all options, nothing specific to validate
|
|
break;
|
|
}
|
|
}
|
|
} |