import * as path from 'path'; import { tap, expect } from '@push.rocks/tapbundle'; import { SmartProxy } from '../ts/proxies/smart-proxy/index.js'; import { createHttpRoute, createHttpsRoute, createPassthroughRoute, createRedirectRoute, createHttpToHttpsRedirect, createBlockRoute, createLoadBalancerRoute, createHttpsServer, createPortRange, createSecurityConfig, createStaticFileRoute, createTestRoute } from '../ts/proxies/smart-proxy/route-helpers/index.js'; import type { IRouteConfig } from '../ts/proxies/smart-proxy/models/route-types.js'; // Test to demonstrate various route configurations using the new helpers tap.test('Route-based configuration examples', async (tools) => { // Example 1: HTTP-only configuration const httpOnlyRoute = createHttpRoute({ domains: 'http.example.com', target: { host: 'localhost', port: 3000 }, security: { allowedIps: ['*'] // Allow all }, name: 'Basic HTTP Route' }); console.log('HTTP-only route created successfully:', httpOnlyRoute.name); expect(httpOnlyRoute.action.type).toEqual('forward'); expect(httpOnlyRoute.match.domains).toEqual('http.example.com'); // Example 2: HTTPS Passthrough (SNI) configuration const httpsPassthroughRoute = createPassthroughRoute({ domains: 'pass.example.com', target: { host: ['10.0.0.1', '10.0.0.2'], // Round-robin target IPs port: 443 }, security: { allowedIps: ['*'] // Allow all }, name: 'HTTPS Passthrough Route' }); expect(httpsPassthroughRoute).toBeTruthy(); expect(httpsPassthroughRoute.action.tls?.mode).toEqual('passthrough'); expect(Array.isArray(httpsPassthroughRoute.action.target?.host)).toBeTrue(); // Example 3: HTTPS Termination to HTTP Backend const terminateToHttpRoute = createHttpsRoute({ domains: 'secure.example.com', target: { host: 'localhost', port: 8080 }, tlsMode: 'terminate', certificate: 'auto', headers: { 'X-Forwarded-Proto': 'https' }, security: { allowedIps: ['*'] // Allow all }, name: 'HTTPS Termination to HTTP Backend' }); // Create the HTTP to HTTPS redirect for this domain const httpToHttpsRedirect = createHttpToHttpsRedirect({ domains: 'secure.example.com', name: 'HTTP to HTTPS Redirect for secure.example.com' }); expect(terminateToHttpRoute).toBeTruthy(); expect(terminateToHttpRoute.action.tls?.mode).toEqual('terminate'); expect(terminateToHttpRoute.action.advanced?.headers?.['X-Forwarded-Proto']).toEqual('https'); expect(httpToHttpsRedirect.action.type).toEqual('redirect'); // Example 4: Load Balancer with HTTPS const loadBalancerRoute = createLoadBalancerRoute({ domains: 'proxy.example.com', targets: ['internal-api-1.local', 'internal-api-2.local'], targetPort: 8443, tlsMode: 'terminate-and-reencrypt', certificate: 'auto', headers: { 'X-Original-Host': '{domain}' }, security: { allowedIps: ['10.0.0.0/24', '192.168.1.0/24'], maxConnections: 1000 }, name: 'Load Balanced HTTPS Route' }); expect(loadBalancerRoute).toBeTruthy(); expect(loadBalancerRoute.action.tls?.mode).toEqual('terminate-and-reencrypt'); expect(Array.isArray(loadBalancerRoute.action.target?.host)).toBeTrue(); expect(loadBalancerRoute.action.security?.allowedIps?.length).toEqual(2); // Example 5: Block specific IPs const blockRoute = createBlockRoute({ ports: [80, 443], clientIp: ['192.168.5.0/24'], name: 'Block Suspicious IPs', priority: 1000 // High priority to ensure it's evaluated first }); expect(blockRoute.action.type).toEqual('block'); expect(blockRoute.match.clientIp?.length).toEqual(1); expect(blockRoute.priority).toEqual(1000); // Example 6: Complete HTTPS Server with HTTP Redirect const httpsServerRoutes = createHttpsServer({ domains: 'complete.example.com', target: { host: 'localhost', port: 8080 }, certificate: 'auto', name: 'Complete HTTPS Server' }); expect(Array.isArray(httpsServerRoutes)).toBeTrue(); expect(httpsServerRoutes.length).toEqual(2); // HTTPS route and HTTP redirect expect(httpsServerRoutes[0].action.tls?.mode).toEqual('terminate'); expect(httpsServerRoutes[1].action.type).toEqual('redirect'); // Example 7: Static File Server const staticFileRoute = createStaticFileRoute({ domains: 'static.example.com', targetDirectory: '/var/www/static', tlsMode: 'terminate', certificate: 'auto', headers: { 'Cache-Control': 'public, max-age=86400' }, name: 'Static File Server' }); expect(staticFileRoute.action.advanced?.staticFiles?.directory).toEqual('/var/www/static'); expect(staticFileRoute.action.advanced?.headers?.['Cache-Control']).toEqual('public, max-age=86400'); // Example 8: Test Route for Debugging const testRoute = createTestRoute({ ports: 8000, domains: 'test.example.com', response: { status: 200, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status: 'ok', message: 'API is working!' }) } }); expect(testRoute.match.ports).toEqual(8000); expect(testRoute.action.advanced?.testResponse?.status).toEqual(200); // Create a SmartProxy instance with all routes const allRoutes: IRouteConfig[] = [ httpOnlyRoute, httpsPassthroughRoute, terminateToHttpRoute, httpToHttpsRedirect, loadBalancerRoute, blockRoute, ...httpsServerRoutes, staticFileRoute, testRoute ]; // We're not actually starting the SmartProxy in this test, // just verifying that the configuration is valid const smartProxy = new SmartProxy({ routes: allRoutes, acme: { email: 'admin@example.com', termsOfServiceAgreed: true, directoryUrl: 'https://acme-staging-v02.api.letsencrypt.org/directory' } }); console.log(`Smart Proxy configured with ${allRoutes.length} routes`); // Verify our example proxy was created correctly expect(smartProxy).toBeTruthy(); }); export default tap.start();