UNPKG

@push.rocks/smartproxy

Version:

A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.

115 lines 9.67 kB
import { DomainMatcher, PathMatcher, IpMatcher, HeaderMatcher } from './matchers/index.js'; /** * Unified route specificity calculator * Provides consistent specificity scoring across all routing components */ export class RouteSpecificity { /** * Calculate the total specificity score for a route * Higher scores indicate more specific routes that should match first */ static calculate(route) { const specificity = { pathSpecificity: 0, domainSpecificity: 0, ipSpecificity: 0, headerSpecificity: 0, tlsSpecificity: 0, totalScore: 0 }; // Path specificity if (route.match.path) { specificity.pathSpecificity = PathMatcher.calculateSpecificity(route.match.path); } // Domain specificity if (route.match.domains) { const domains = Array.isArray(route.match.domains) ? route.match.domains : [route.match.domains]; // Use the highest specificity among all domains specificity.domainSpecificity = Math.max(...domains.map(d => DomainMatcher.calculateSpecificity(d))); } // IP specificity (clientIp is an array of IPs) if (route.match.clientIp && route.match.clientIp.length > 0) { // Use the first IP pattern for specificity calculation specificity.ipSpecificity = IpMatcher.calculateSpecificity(route.match.clientIp[0]); } // Header specificity (convert RegExp values to strings) if (route.match.headers) { const stringHeaders = {}; for (const [key, value] of Object.entries(route.match.headers)) { stringHeaders[key] = value instanceof RegExp ? value.source : value; } specificity.headerSpecificity = HeaderMatcher.calculateSpecificity(stringHeaders); } // TLS version specificity if (route.match.tlsVersion && route.match.tlsVersion.length > 0) { specificity.tlsSpecificity = route.match.tlsVersion.length * 10; } // Calculate total score with weights specificity.totalScore = specificity.pathSpecificity * 3 + // Path is most important specificity.domainSpecificity * 2 + // Domain is second specificity.ipSpecificity * 1.5 + // IP is moderately important specificity.headerSpecificity * 1 + // Headers are less important specificity.tlsSpecificity * 0.5; // TLS is least important return specificity; } /** * Compare two routes and determine which is more specific * @returns positive if route1 is more specific, negative if route2 is more specific, 0 if equal */ static compare(route1, route2) { const spec1 = this.calculate(route1); const spec2 = this.calculate(route2); // First compare by total score if (spec1.totalScore !== spec2.totalScore) { return spec1.totalScore - spec2.totalScore; } // If total scores are equal, compare by individual components // Path is most important tiebreaker if (spec1.pathSpecificity !== spec2.pathSpecificity) { return spec1.pathSpecificity - spec2.pathSpecificity; } // Then domain if (spec1.domainSpecificity !== spec2.domainSpecificity) { return spec1.domainSpecificity - spec2.domainSpecificity; } // Then IP if (spec1.ipSpecificity !== spec2.ipSpecificity) { return spec1.ipSpecificity - spec2.ipSpecificity; } // Then headers if (spec1.headerSpecificity !== spec2.headerSpecificity) { return spec1.headerSpecificity - spec2.headerSpecificity; } // Finally TLS return spec1.tlsSpecificity - spec2.tlsSpecificity; } /** * Sort routes by specificity (most specific first) */ static sort(routes) { return [...routes].sort((a, b) => this.compare(b, a)); } /** * Find the most specific route from a list */ static findMostSpecific(routes) { if (routes.length === 0) return null; return routes.reduce((most, current) => this.compare(current, most) > 0 ? current : most); } /** * Check if a route has any matching criteria */ static hasMatchCriteria(route) { const match = route.match; return !!(match.domains || match.path || match.clientIp?.length || match.headers || match.tlsVersion?.length); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BlY2lmaWNpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb3JlL3JvdXRpbmcvc3BlY2lmaWNpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxFQUFFLGFBQWEsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRTNGOzs7R0FHRztBQUNILE1BQU0sT0FBTyxnQkFBZ0I7SUFDM0I7OztPQUdHO0lBQ0gsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFtQjtRQUNsQyxNQUFNLFdBQVcsR0FBc0I7WUFDckMsZUFBZSxFQUFFLENBQUM7WUFDbEIsaUJBQWlCLEVBQUUsQ0FBQztZQUNwQixhQUFhLEVBQUUsQ0FBQztZQUNoQixpQkFBaUIsRUFBRSxDQUFDO1lBQ3BCLGNBQWMsRUFBRSxDQUFDO1lBQ2pCLFVBQVUsRUFBRSxDQUFDO1NBQ2QsQ0FBQztRQUVGLG1CQUFtQjtRQUNuQixJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDckIsV0FBVyxDQUFDLGVBQWUsR0FBRyxXQUFXLENBQUMsb0JBQW9CLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNuRixDQUFDO1FBRUQscUJBQXFCO1FBQ3JCLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUN4QixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDO2dCQUNoRCxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFPO2dCQUNyQixDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRTFCLGdEQUFnRDtZQUNoRCxXQUFXLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FDdEMsR0FBRyxPQUFPLENBQUMs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