187 lines
7.7 KiB
TypeScript
187 lines
7.7 KiB
TypeScript
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||
|
import * as plugins from '../ts/plugins.js';
|
||
|
import type { IForwardConfig, ForwardingType } from '../ts/smartproxy/types/forwarding.types.js';
|
||
|
|
||
|
// First, import the components directly to avoid issues with compiled modules
|
||
|
import { ForwardingHandlerFactory } from '../ts/smartproxy/forwarding/forwarding.factory.js';
|
||
|
import { createDomainConfig } from '../ts/smartproxy/forwarding/domain-config.js';
|
||
|
import { DomainManager } from '../ts/smartproxy/forwarding/domain-manager.js';
|
||
|
import { httpOnly, tlsTerminateToHttp, tlsTerminateToHttps, sniPassthrough } from '../ts/smartproxy/types/forwarding.types.js';
|
||
|
|
||
|
const helpers = {
|
||
|
httpOnly,
|
||
|
tlsTerminateToHttp,
|
||
|
tlsTerminateToHttps,
|
||
|
sniPassthrough
|
||
|
};
|
||
|
|
||
|
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('DomainManager - manage domain configurations', async () => {
|
||
|
const domainManager = new DomainManager();
|
||
|
|
||
|
// Add a domain configuration
|
||
|
await domainManager.addDomainConfig(
|
||
|
createDomainConfig('example.com', helpers.httpOnly('localhost', 3000))
|
||
|
);
|
||
|
|
||
|
// Check that the configuration was added
|
||
|
const configs = domainManager.getDomainConfigs();
|
||
|
expect(configs.length).toEqual(1);
|
||
|
expect(configs[0].domains[0]).toEqual('example.com');
|
||
|
expect(configs[0].forwarding.type).toEqual('http-only');
|
||
|
|
||
|
// Find a handler for a domain
|
||
|
const handler = domainManager.findHandlerForDomain('example.com');
|
||
|
expect(handler).toBeDefined();
|
||
|
|
||
|
// Remove a domain configuration
|
||
|
const removed = domainManager.removeDomainConfig('example.com');
|
||
|
expect(removed).toBeTrue();
|
||
|
|
||
|
// Check that the configuration was removed
|
||
|
const configsAfterRemoval = domainManager.getDomainConfigs();
|
||
|
expect(configsAfterRemoval.length).toEqual(0);
|
||
|
|
||
|
// Check that no handler exists anymore
|
||
|
const handlerAfterRemoval = domainManager.findHandlerForDomain('example.com');
|
||
|
expect(handlerAfterRemoval).toBeUndefined();
|
||
|
});
|
||
|
|
||
|
tap.test('DomainManager - support wildcard domains', async () => {
|
||
|
const domainManager = new DomainManager();
|
||
|
|
||
|
// Add a wildcard domain configuration
|
||
|
await domainManager.addDomainConfig(
|
||
|
createDomainConfig('*.example.com', helpers.httpOnly('localhost', 3000))
|
||
|
);
|
||
|
|
||
|
// Find a handler for a subdomain
|
||
|
const handler = domainManager.findHandlerForDomain('test.example.com');
|
||
|
expect(handler).toBeDefined();
|
||
|
|
||
|
// Find a handler for a different domain (should not match)
|
||
|
const noHandler = domainManager.findHandlerForDomain('example.org');
|
||
|
expect(noHandler).toBeUndefined();
|
||
|
});
|
||
|
tap.test('Helper Functions - create http-only forwarding config', async () => {
|
||
|
const config = helpers.httpOnly('localhost', 3000);
|
||
|
expect(config.type).toEqual('http-only');
|
||
|
expect(config.target.host).toEqual('localhost');
|
||
|
expect(config.target.port).toEqual(3000);
|
||
|
expect(config.http?.enabled).toBeTrue();
|
||
|
});
|
||
|
|
||
|
tap.test('Helper Functions - create https-terminate-to-http config', async () => {
|
||
|
const config = helpers.tlsTerminateToHttp('localhost', 3000);
|
||
|
expect(config.type).toEqual('https-terminate-to-http');
|
||
|
expect(config.target.host).toEqual('localhost');
|
||
|
expect(config.target.port).toEqual(3000);
|
||
|
expect(config.http?.redirectToHttps).toBeTrue();
|
||
|
expect(config.acme?.enabled).toBeTrue();
|
||
|
expect(config.acme?.maintenance).toBeTrue();
|
||
|
});
|
||
|
|
||
|
tap.test('Helper Functions - create https-terminate-to-https config', async () => {
|
||
|
const config = helpers.tlsTerminateToHttps('localhost', 8443);
|
||
|
expect(config.type).toEqual('https-terminate-to-https');
|
||
|
expect(config.target.host).toEqual('localhost');
|
||
|
expect(config.target.port).toEqual(8443);
|
||
|
expect(config.http?.redirectToHttps).toBeTrue();
|
||
|
expect(config.acme?.enabled).toBeTrue();
|
||
|
expect(config.acme?.maintenance).toBeTrue();
|
||
|
});
|
||
|
|
||
|
tap.test('Helper Functions - create https-passthrough config', async () => {
|
||
|
const config = helpers.sniPassthrough('localhost', 443);
|
||
|
expect(config.type).toEqual('https-passthrough');
|
||
|
expect(config.target.host).toEqual('localhost');
|
||
|
expect(config.target.port).toEqual(443);
|
||
|
expect(config.https?.forwardSni).toBeTrue();
|
||
|
});
|
||
|
export default tap.start();
|