import { tap, expect } from '@push.rocks/tapbundle'; import * as plugins from '../ts/plugins.js'; import type { IForwardConfig, TForwardingType } from '../ts/forwarding/config/forwarding-types.js'; // First, import the components directly to avoid issues with compiled modules import { ForwardingHandlerFactory } from '../ts/forwarding/factory/forwarding-factory.js'; import { httpOnly, tlsTerminateToHttp, tlsTerminateToHttps, httpsPassthrough } from '../ts/forwarding/config/forwarding-types.js'; // Import route-based helpers import { createHttpRoute, createHttpsTerminateRoute, createHttpsPassthroughRoute, createHttpToHttpsRedirect, createCompleteHttpsServer } from '../ts/proxies/smart-proxy/utils/route-helpers.js'; const helpers = { httpOnly, tlsTerminateToHttp, tlsTerminateToHttps, httpsPassthrough }; // Route-based utility functions for testing function findRouteForDomain(routes: any[], domain: string): any { return routes.find(route => { const domains = Array.isArray(route.match.domains) ? route.match.domains : [route.match.domains]; return domains.some(d => { // Handle wildcard domains if (d.startsWith('*.')) { const suffix = d.substring(2); return domain.endsWith(suffix) && domain.split('.').length > suffix.split('.').length; } return d === domain; }); }); } tap.test('ForwardingHandlerFactory - apply defaults based on type', async () => { // HTTP-only defaults const httpConfig: IForwardConfig = { type: 'http-only', target: { host: 'localhost', port: 3000 } }; const expandedHttpConfig = ForwardingHandlerFactory.applyDefaults(httpConfig); expect(expandedHttpConfig.http?.enabled).toEqual(true); // HTTPS-passthrough defaults const passthroughConfig: IForwardConfig = { type: 'https-passthrough', target: { host: 'localhost', port: 443 } }; const expandedPassthroughConfig = ForwardingHandlerFactory.applyDefaults(passthroughConfig); expect(expandedPassthroughConfig.https?.forwardSni).toEqual(true); expect(expandedPassthroughConfig.http?.enabled).toEqual(false); // HTTPS-terminate-to-http defaults const terminateToHttpConfig: IForwardConfig = { type: 'https-terminate-to-http', target: { host: 'localhost', port: 3000 } }; const expandedTerminateToHttpConfig = ForwardingHandlerFactory.applyDefaults(terminateToHttpConfig); expect(expandedTerminateToHttpConfig.http?.enabled).toEqual(true); expect(expandedTerminateToHttpConfig.http?.redirectToHttps).toEqual(true); expect(expandedTerminateToHttpConfig.acme?.enabled).toEqual(true); expect(expandedTerminateToHttpConfig.acme?.maintenance).toEqual(true); // HTTPS-terminate-to-https defaults const terminateToHttpsConfig: IForwardConfig = { type: 'https-terminate-to-https', target: { host: 'localhost', port: 8443 } }; const expandedTerminateToHttpsConfig = ForwardingHandlerFactory.applyDefaults(terminateToHttpsConfig); expect(expandedTerminateToHttpsConfig.http?.enabled).toEqual(true); expect(expandedTerminateToHttpsConfig.http?.redirectToHttps).toEqual(true); expect(expandedTerminateToHttpsConfig.acme?.enabled).toEqual(true); expect(expandedTerminateToHttpsConfig.acme?.maintenance).toEqual(true); }); tap.test('ForwardingHandlerFactory - validate configuration', async () => { // Valid configuration const validConfig: IForwardConfig = { type: 'http-only', target: { host: 'localhost', port: 3000 } }; expect(() => ForwardingHandlerFactory.validateConfig(validConfig)).not.toThrow(); // Invalid configuration - missing target const invalidConfig1: any = { type: 'http-only' }; expect(() => ForwardingHandlerFactory.validateConfig(invalidConfig1)).toThrow(); // Invalid configuration - invalid port const invalidConfig2: IForwardConfig = { type: 'http-only', target: { host: 'localhost', port: 0 } }; expect(() => ForwardingHandlerFactory.validateConfig(invalidConfig2)).toThrow(); // Invalid configuration - HTTP disabled for HTTP-only const invalidConfig3: IForwardConfig = { type: 'http-only', target: { host: 'localhost', port: 3000 }, http: { enabled: false } }; expect(() => ForwardingHandlerFactory.validateConfig(invalidConfig3)).toThrow(); // Invalid configuration - HTTP enabled for HTTPS passthrough const invalidConfig4: IForwardConfig = { type: 'https-passthrough', target: { host: 'localhost', port: 443 }, http: { enabled: true } }; expect(() => ForwardingHandlerFactory.validateConfig(invalidConfig4)).toThrow(); }); tap.test('Route Management - manage route configurations', async () => { // Create an array to store routes const routes: any[] = []; // Add a route configuration const httpRoute = createHttpRoute('example.com', { host: 'localhost', port: 3000 }); routes.push(httpRoute); // Check that the configuration was added expect(routes.length).toEqual(1); expect(routes[0].match.domains).toEqual('example.com'); expect(routes[0].action.type).toEqual('forward'); expect(routes[0].action.target.host).toEqual('localhost'); expect(routes[0].action.target.port).toEqual(3000); // Find a route for a domain const foundRoute = findRouteForDomain(routes, 'example.com'); expect(foundRoute).toBeDefined(); // Remove a route configuration const initialLength = routes.length; const domainToRemove = 'example.com'; const indexToRemove = routes.findIndex(route => { const domains = Array.isArray(route.match.domains) ? route.match.domains : [route.match.domains]; return domains.includes(domainToRemove); }); if (indexToRemove !== -1) { routes.splice(indexToRemove, 1); } expect(routes.length).toEqual(initialLength - 1); // Check that the configuration was removed expect(routes.length).toEqual(0); // Check that no route exists anymore const notFoundRoute = findRouteForDomain(routes, 'example.com'); expect(notFoundRoute).toBeUndefined(); }); tap.test('Route Management - support wildcard domains', async () => { // Create an array to store routes const routes: any[] = []; // Add a wildcard domain route const wildcardRoute = createHttpRoute('*.example.com', { host: 'localhost', port: 3000 }); routes.push(wildcardRoute); // Find a route for a subdomain const foundRoute = findRouteForDomain(routes, 'test.example.com'); expect(foundRoute).toBeDefined(); // Find a route for a different domain (should not match) const notFoundRoute = findRouteForDomain(routes, 'example.org'); expect(notFoundRoute).toBeUndefined(); }); tap.test('Route Helper Functions - create HTTP route', async () => { const route = createHttpRoute('example.com', { host: 'localhost', port: 3000 }); expect(route.match.domains).toEqual('example.com'); expect(route.match.ports).toEqual(80); expect(route.action.type).toEqual('forward'); expect(route.action.target.host).toEqual('localhost'); expect(route.action.target.port).toEqual(3000); }); tap.test('Route Helper Functions - create HTTPS terminate route', async () => { const route = createHttpsTerminateRoute('example.com', { host: 'localhost', port: 3000 }); expect(route.match.domains).toEqual('example.com'); expect(route.match.ports).toEqual(443); expect(route.action.type).toEqual('forward'); expect(route.action.target.host).toEqual('localhost'); expect(route.action.target.port).toEqual(3000); expect(route.action.tls?.mode).toEqual('terminate'); expect(route.action.tls?.certificate).toEqual('auto'); }); tap.test('Route Helper Functions - create complete HTTPS server', async () => { const routes = createCompleteHttpsServer('example.com', { host: 'localhost', port: 8443 }); expect(routes.length).toEqual(2); // HTTPS route expect(routes[0].match.domains).toEqual('example.com'); expect(routes[0].match.ports).toEqual(443); expect(routes[0].action.type).toEqual('forward'); expect(routes[0].action.target.host).toEqual('localhost'); expect(routes[0].action.target.port).toEqual(8443); expect(routes[0].action.tls?.mode).toEqual('terminate'); // HTTP redirect route expect(routes[1].match.domains).toEqual('example.com'); expect(routes[1].match.ports).toEqual(80); expect(routes[1].action.type).toEqual('redirect'); }); tap.test('Route Helper Functions - create HTTPS passthrough route', async () => { const route = createHttpsPassthroughRoute('example.com', { host: 'localhost', port: 443 }); expect(route.match.domains).toEqual('example.com'); expect(route.match.ports).toEqual(443); expect(route.action.type).toEqual('forward'); expect(route.action.target.host).toEqual('localhost'); expect(route.action.target.port).toEqual(443); expect(route.action.tls?.mode).toEqual('passthrough'); }); export default tap.start();