497 lines
12 KiB
TypeScript
497 lines
12 KiB
TypeScript
import type {
|
|
IRouteConfig,
|
|
IRouteMatch,
|
|
IRouteAction,
|
|
IRouteTarget,
|
|
IRouteTls,
|
|
IRouteRedirect,
|
|
IRouteSecurity,
|
|
IRouteAdvanced,
|
|
TPortRange
|
|
} from './models/route-types.js';
|
|
|
|
/**
|
|
* Basic helper function to create a route configuration
|
|
*/
|
|
export function createRoute(
|
|
match: IRouteMatch,
|
|
action: IRouteAction,
|
|
metadata?: {
|
|
name?: string;
|
|
description?: string;
|
|
priority?: number;
|
|
tags?: string[];
|
|
}
|
|
): IRouteConfig {
|
|
return {
|
|
match,
|
|
action,
|
|
...metadata
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create a basic HTTP route configuration
|
|
*/
|
|
export function createHttpRoute(
|
|
options: {
|
|
ports?: number | number[]; // Default: 80
|
|
domains?: string | string[];
|
|
path?: string;
|
|
target: IRouteTarget;
|
|
headers?: Record<string, string>;
|
|
security?: IRouteSecurity;
|
|
name?: string;
|
|
description?: string;
|
|
priority?: number;
|
|
tags?: string[];
|
|
}
|
|
): IRouteConfig {
|
|
return createRoute(
|
|
{
|
|
ports: options.ports || 80,
|
|
...(options.domains ? { domains: options.domains } : {}),
|
|
...(options.path ? { path: options.path } : {})
|
|
},
|
|
{
|
|
type: 'forward',
|
|
target: options.target,
|
|
...(options.headers || options.security ? {
|
|
advanced: {
|
|
...(options.headers ? { headers: options.headers } : {})
|
|
},
|
|
...(options.security ? { security: options.security } : {})
|
|
} : {})
|
|
},
|
|
{
|
|
name: options.name || 'HTTP Route',
|
|
description: options.description,
|
|
priority: options.priority,
|
|
tags: options.tags
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create an HTTPS route configuration with TLS termination
|
|
*/
|
|
export function createHttpsRoute(
|
|
options: {
|
|
ports?: number | number[]; // Default: 443
|
|
domains: string | string[];
|
|
path?: string;
|
|
target: IRouteTarget;
|
|
tlsMode?: 'terminate' | 'terminate-and-reencrypt';
|
|
certificate?: 'auto' | { key: string; cert: string };
|
|
headers?: Record<string, string>;
|
|
security?: IRouteSecurity;
|
|
name?: string;
|
|
description?: string;
|
|
priority?: number;
|
|
tags?: string[];
|
|
}
|
|
): IRouteConfig {
|
|
return createRoute(
|
|
{
|
|
ports: options.ports || 443,
|
|
domains: options.domains,
|
|
...(options.path ? { path: options.path } : {})
|
|
},
|
|
{
|
|
type: 'forward',
|
|
target: options.target,
|
|
tls: {
|
|
mode: options.tlsMode || 'terminate',
|
|
certificate: options.certificate || 'auto'
|
|
},
|
|
...(options.headers || options.security ? {
|
|
advanced: {
|
|
...(options.headers ? { headers: options.headers } : {})
|
|
},
|
|
...(options.security ? { security: options.security } : {})
|
|
} : {})
|
|
},
|
|
{
|
|
name: options.name || 'HTTPS Route',
|
|
description: options.description,
|
|
priority: options.priority,
|
|
tags: options.tags
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create an HTTPS passthrough route configuration
|
|
*/
|
|
export function createPassthroughRoute(
|
|
options: {
|
|
ports?: number | number[]; // Default: 443
|
|
domains?: string | string[];
|
|
target: IRouteTarget;
|
|
security?: IRouteSecurity;
|
|
name?: string;
|
|
description?: string;
|
|
priority?: number;
|
|
tags?: string[];
|
|
}
|
|
): IRouteConfig {
|
|
return createRoute(
|
|
{
|
|
ports: options.ports || 443,
|
|
...(options.domains ? { domains: options.domains } : {})
|
|
},
|
|
{
|
|
type: 'forward',
|
|
target: options.target,
|
|
tls: {
|
|
mode: 'passthrough'
|
|
},
|
|
...(options.security ? { security: options.security } : {})
|
|
},
|
|
{
|
|
name: options.name || 'HTTPS Passthrough Route',
|
|
description: options.description,
|
|
priority: options.priority,
|
|
tags: options.tags
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create a redirect route configuration
|
|
*/
|
|
export function createRedirectRoute(
|
|
options: {
|
|
ports?: number | number[]; // Default: 80
|
|
domains?: string | string[];
|
|
path?: string;
|
|
redirectTo: string;
|
|
statusCode?: 301 | 302 | 307 | 308;
|
|
name?: string;
|
|
description?: string;
|
|
priority?: number;
|
|
tags?: string[];
|
|
}
|
|
): IRouteConfig {
|
|
return createRoute(
|
|
{
|
|
ports: options.ports || 80,
|
|
...(options.domains ? { domains: options.domains } : {}),
|
|
...(options.path ? { path: options.path } : {})
|
|
},
|
|
{
|
|
type: 'redirect',
|
|
redirect: {
|
|
to: options.redirectTo,
|
|
status: options.statusCode || 301
|
|
}
|
|
},
|
|
{
|
|
name: options.name || 'Redirect Route',
|
|
description: options.description,
|
|
priority: options.priority,
|
|
tags: options.tags
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create an HTTP to HTTPS redirect route configuration
|
|
*/
|
|
export function createHttpToHttpsRedirect(
|
|
options: {
|
|
domains: string | string[];
|
|
statusCode?: 301 | 302 | 307 | 308;
|
|
name?: string;
|
|
priority?: number;
|
|
}
|
|
): IRouteConfig {
|
|
const domainArray = Array.isArray(options.domains) ? options.domains : [options.domains];
|
|
|
|
return createRedirectRoute({
|
|
ports: 80,
|
|
domains: options.domains,
|
|
redirectTo: 'https://{domain}{path}',
|
|
statusCode: options.statusCode || 301,
|
|
name: options.name || `HTTP to HTTPS Redirect for ${domainArray.join(', ')}`,
|
|
priority: options.priority || 100 // High priority for redirects
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Create a block route configuration
|
|
*/
|
|
export function createBlockRoute(
|
|
options: {
|
|
ports: number | number[];
|
|
domains?: string | string[];
|
|
clientIp?: string[];
|
|
name?: string;
|
|
description?: string;
|
|
priority?: number;
|
|
tags?: string[];
|
|
}
|
|
): IRouteConfig {
|
|
return createRoute(
|
|
{
|
|
ports: options.ports,
|
|
...(options.domains ? { domains: options.domains } : {}),
|
|
...(options.clientIp ? { clientIp: options.clientIp } : {})
|
|
},
|
|
{
|
|
type: 'block'
|
|
},
|
|
{
|
|
name: options.name || 'Block Route',
|
|
description: options.description,
|
|
priority: options.priority || 1000, // Very high priority for blocks
|
|
tags: options.tags
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create a load balancer route configuration
|
|
*/
|
|
export function createLoadBalancerRoute(
|
|
options: {
|
|
ports?: number | number[]; // Default: 443
|
|
domains: string | string[];
|
|
path?: string;
|
|
targets: string[]; // Array of host names/IPs for load balancing
|
|
targetPort: number;
|
|
tlsMode?: 'passthrough' | 'terminate' | 'terminate-and-reencrypt';
|
|
certificate?: 'auto' | { key: string; cert: string };
|
|
headers?: Record<string, string>;
|
|
security?: IRouteSecurity;
|
|
name?: string;
|
|
description?: string;
|
|
tags?: string[];
|
|
}
|
|
): IRouteConfig {
|
|
const useTls = options.tlsMode !== undefined;
|
|
const defaultPort = useTls ? 443 : 80;
|
|
|
|
return createRoute(
|
|
{
|
|
ports: options.ports || defaultPort,
|
|
domains: options.domains,
|
|
...(options.path ? { path: options.path } : {})
|
|
},
|
|
{
|
|
type: 'forward',
|
|
target: {
|
|
host: options.targets,
|
|
port: options.targetPort
|
|
},
|
|
...(useTls ? {
|
|
tls: {
|
|
mode: options.tlsMode!,
|
|
...(options.tlsMode !== 'passthrough' && options.certificate ? {
|
|
certificate: options.certificate
|
|
} : {})
|
|
}
|
|
} : {}),
|
|
...(options.headers || options.security ? {
|
|
advanced: {
|
|
...(options.headers ? { headers: options.headers } : {})
|
|
},
|
|
...(options.security ? { security: options.security } : {})
|
|
} : {})
|
|
},
|
|
{
|
|
name: options.name || 'Load Balanced Route',
|
|
description: options.description || `Load balancing across ${options.targets.length} backends`,
|
|
tags: options.tags
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create a complete HTTPS server configuration with HTTP redirect
|
|
*/
|
|
export function createHttpsServer(
|
|
options: {
|
|
domains: string | string[];
|
|
target: IRouteTarget;
|
|
certificate?: 'auto' | { key: string; cert: string };
|
|
security?: IRouteSecurity;
|
|
addHttpRedirect?: boolean;
|
|
name?: string;
|
|
}
|
|
): IRouteConfig[] {
|
|
const routes: IRouteConfig[] = [];
|
|
const domainArray = Array.isArray(options.domains) ? options.domains : [options.domains];
|
|
|
|
// Add HTTPS route
|
|
routes.push(createHttpsRoute({
|
|
domains: options.domains,
|
|
target: options.target,
|
|
certificate: options.certificate || 'auto',
|
|
security: options.security,
|
|
name: options.name || `HTTPS Server for ${domainArray.join(', ')}`
|
|
}));
|
|
|
|
// Add HTTP to HTTPS redirect if requested
|
|
if (options.addHttpRedirect !== false) {
|
|
routes.push(createHttpToHttpsRedirect({
|
|
domains: options.domains,
|
|
name: `HTTP to HTTPS Redirect for ${domainArray.join(', ')}`,
|
|
priority: 100
|
|
}));
|
|
}
|
|
|
|
return routes;
|
|
}
|
|
|
|
/**
|
|
* Create a port range configuration from various input formats
|
|
*/
|
|
export function createPortRange(
|
|
ports: number | number[] | string | Array<{ from: number; to: number }>
|
|
): TPortRange {
|
|
// If it's a string like "80,443" or "8000-9000", parse it
|
|
if (typeof ports === 'string') {
|
|
if (ports.includes('-')) {
|
|
// Handle range like "8000-9000"
|
|
const [start, end] = ports.split('-').map(p => parseInt(p.trim(), 10));
|
|
return [{ from: start, to: end }];
|
|
} else if (ports.includes(',')) {
|
|
// Handle comma-separated list like "80,443,8080"
|
|
return ports.split(',').map(p => parseInt(p.trim(), 10));
|
|
} else {
|
|
// Handle single port as string
|
|
return parseInt(ports.trim(), 10);
|
|
}
|
|
}
|
|
|
|
// Otherwise return as is
|
|
return ports;
|
|
}
|
|
|
|
/**
|
|
* Create a security configuration object
|
|
*/
|
|
export function createSecurityConfig(
|
|
options: {
|
|
allowedIps?: string[];
|
|
blockedIps?: string[];
|
|
maxConnections?: number;
|
|
authentication?: {
|
|
type: 'basic' | 'digest' | 'oauth';
|
|
// Auth-specific options
|
|
[key: string]: any;
|
|
};
|
|
}
|
|
): IRouteSecurity {
|
|
return {
|
|
...(options.allowedIps ? { allowedIps: options.allowedIps } : {}),
|
|
...(options.blockedIps ? { blockedIps: options.blockedIps } : {}),
|
|
...(options.maxConnections ? { maxConnections: options.maxConnections } : {}),
|
|
...(options.authentication ? { authentication: options.authentication } : {})
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create a static file server route
|
|
*/
|
|
export function createStaticFileRoute(
|
|
options: {
|
|
ports?: number | number[]; // Default: 80
|
|
domains: string | string[];
|
|
path?: string;
|
|
targetDirectory: string;
|
|
tlsMode?: 'terminate' | 'terminate-and-reencrypt';
|
|
certificate?: 'auto' | { key: string; cert: string };
|
|
headers?: Record<string, string>;
|
|
security?: IRouteSecurity;
|
|
name?: string;
|
|
description?: string;
|
|
priority?: number;
|
|
tags?: string[];
|
|
}
|
|
): IRouteConfig {
|
|
const useTls = options.tlsMode !== undefined;
|
|
const defaultPort = useTls ? 443 : 80;
|
|
|
|
return createRoute(
|
|
{
|
|
ports: options.ports || defaultPort,
|
|
domains: options.domains,
|
|
...(options.path ? { path: options.path } : {})
|
|
},
|
|
{
|
|
type: 'forward',
|
|
target: {
|
|
host: 'localhost', // Static file serving is typically handled locally
|
|
port: 0, // Special value indicating a static file server
|
|
preservePort: false
|
|
},
|
|
...(useTls ? {
|
|
tls: {
|
|
mode: options.tlsMode!,
|
|
certificate: options.certificate || 'auto'
|
|
}
|
|
} : {}),
|
|
advanced: {
|
|
...(options.headers ? { headers: options.headers } : {}),
|
|
staticFiles: {
|
|
directory: options.targetDirectory,
|
|
indexFiles: ['index.html', 'index.htm']
|
|
}
|
|
},
|
|
...(options.security ? { security: options.security } : {})
|
|
},
|
|
{
|
|
name: options.name || 'Static File Server',
|
|
description: options.description || `Serving static files from ${options.targetDirectory}`,
|
|
priority: options.priority,
|
|
tags: options.tags
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create a test route for debugging purposes
|
|
*/
|
|
export function createTestRoute(
|
|
options: {
|
|
ports?: number | number[]; // Default: 8000
|
|
domains?: string | string[];
|
|
path?: string;
|
|
response?: {
|
|
status?: number;
|
|
headers?: Record<string, string>;
|
|
body?: string;
|
|
};
|
|
name?: string;
|
|
}
|
|
): IRouteConfig {
|
|
return createRoute(
|
|
{
|
|
ports: options.ports || 8000,
|
|
...(options.domains ? { domains: options.domains } : {}),
|
|
...(options.path ? { path: options.path } : {})
|
|
},
|
|
{
|
|
type: 'forward',
|
|
target: {
|
|
host: 'test', // Special value indicating a test route
|
|
port: 0
|
|
},
|
|
advanced: {
|
|
testResponse: {
|
|
status: options.response?.status || 200,
|
|
headers: options.response?.headers || { 'Content-Type': 'text/plain' },
|
|
body: options.response?.body || 'Test route is working!'
|
|
}
|
|
}
|
|
},
|
|
{
|
|
name: options.name || 'Test Route',
|
|
description: 'Route for testing and debugging',
|
|
priority: 500,
|
|
tags: ['test', 'debug']
|
|
}
|
|
);
|
|
} |