diff --git a/src/squid-config.test.ts b/src/squid-config.test.ts index 19a4c3c63..f1b94d204 100644 --- a/src/squid-config.test.ts +++ b/src/squid-config.test.ts @@ -129,6 +129,46 @@ describe('generateSquidConfig', () => { }); }); + describe('Bare Hostname Handling', () => { + it('should handle bare hostnames without adding leading dot', () => { + // Bare hostnames (no dots) like Docker container names should not get a leading dot + // because they have no subdomains to match + const config: SquidConfig = { + domains: ['api-proxy', 'localhost'], + port: defaultPort, + }; + const result = generateSquidConfig(config); + expect(result).toContain('acl allowed_domains dstdomain api-proxy'); + expect(result).toContain('acl allowed_domains dstdomain localhost'); + expect(result).not.toContain('.api-proxy'); + expect(result).not.toContain('.localhost'); + }); + + it('should handle mixed bare hostnames and FQDNs', () => { + const config: SquidConfig = { + domains: ['api-proxy', 'github.com', 'localhost', 'example.org'], + port: defaultPort, + }; + const result = generateSquidConfig(config); + // Bare hostnames without leading dot + expect(result).toContain('acl allowed_domains dstdomain api-proxy'); + expect(result).toContain('acl allowed_domains dstdomain localhost'); + // FQDNs with leading dot + expect(result).toContain('acl allowed_domains dstdomain .github.com'); + expect(result).toContain('acl allowed_domains dstdomain .example.org'); + }); + + it('should handle bare hostnames with protocol prefixes', () => { + const config: SquidConfig = { + domains: ['http://api-proxy'], + port: defaultPort, + }; + const result = generateSquidConfig(config); + expect(result).toContain('acl allowed_http_only dstdomain api-proxy'); + expect(result).not.toContain('.api-proxy'); + }); + }); + describe('Redundant Subdomain Removal', () => { it('should remove subdomain when parent domain is present', () => { const config: SquidConfig = { @@ -293,12 +333,14 @@ describe('generateSquidConfig', () => { }); it('should handle TLD-only domain (edge case)', () => { + // TLD-only (e.g., 'com') is a bare hostname with no dots, so no leading dot const config: SquidConfig = { domains: ['com'], port: defaultPort, }; const result = generateSquidConfig(config); - expect(result).toContain('acl allowed_domains dstdomain .com'); + expect(result).toContain('acl allowed_domains dstdomain com'); + expect(result).not.toContain('.com'); }); }); diff --git a/src/squid-config.ts b/src/squid-config.ts index 5e1478d6d..92c02db88 100644 --- a/src/squid-config.ts +++ b/src/squid-config.ts @@ -53,10 +53,31 @@ interface PatternsByProtocol { } /** - * Helper to add leading dot to domain for Squid subdomain matching + * Helper to format domain for Squid ACL matching + * + * For fully qualified domains (containing dots), adds a leading dot to enable + * subdomain matching (e.g., .github.com matches both github.com and api.github.com). + * + * For bare hostnames (no dots, like Docker container names), returns as-is without + * a leading dot since bare hostnames have no subdomains to match. + * + * @param domain - Domain or hostname to format + * @returns Formatted string for Squid dstdomain ACL */ function formatDomainForSquid(domain: string): string { - return domain.startsWith('.') ? domain : `.${domain}`; + // Already has leading dot - return as-is + if (domain.startsWith('.')) { + return domain; + } + + // Bare hostname (no dots) - return as-is (e.g., 'api-proxy', 'localhost') + // These are typically Docker container names or single-word hostnames + if (!domain.includes('.')) { + return domain; + } + + // Fully qualified domain - add leading dot for subdomain matching + return `.${domain}`; } /**