new plan
This commit is contained in:
parent
09fc71f051
commit
552f4c246b
938
readme.plan.md
938
readme.plan.md
@ -1,255 +1,775 @@
|
|||||||
# SmartProxy Interface & Type Naming Standardization Plan
|
# SmartProxy Fully Unified Configuration Plan
|
||||||
|
|
||||||
## Project Goal
|
## Project Goal
|
||||||
Standardize interface and type naming throughout the SmartProxy codebase to improve maintainability, readability, and developer experience by:
|
Redesign SmartProxy's configuration for a more elegant, unified, and comprehensible approach by:
|
||||||
1. Ensuring all interfaces are prefixed with "I"
|
1. Creating a single, unified configuration model that covers both "where to listen" and "how to forward"
|
||||||
2. Ensuring all type aliases are prefixed with "T"
|
2. Eliminating the confusion between domain configs and port forwarding
|
||||||
3. Maintaining backward compatibility through type aliases
|
3. Providing a clear, declarative API that makes the intent obvious
|
||||||
4. Updating documentation to reflect naming conventions
|
4. Enhancing maintainability and extensibility for future features
|
||||||
|
|
||||||
## Phase 2: Core Module Standardization
|
## Current Issues
|
||||||
|
|
||||||
- [ ] Update core module interfaces and types
|
The current approach has several issues:
|
||||||
- [ ] Rename interfaces in `ts/core/models/common-types.ts`
|
|
||||||
- [ ] `AcmeOptions` → `IAcmeOptions`
|
|
||||||
- [ ] `DomainOptions` → `IDomainOptions`
|
|
||||||
- [ ] Other common interfaces
|
|
||||||
- [ ] Add backward compatibility aliases
|
|
||||||
- [ ] Update imports throughout core module
|
|
||||||
|
|
||||||
- [ ] Update core utility type definitions
|
1. **Dual Configuration Systems**:
|
||||||
- [ ] Update `ts/core/utils/validation-utils.ts`
|
- Port configuration (`fromPort`, `toPort`, `globalPortRanges`) for "where to listen"
|
||||||
- [ ] Update `ts/core/utils/ip-utils.ts`
|
- Domain configuration (`domainConfigs`) for "how to forward"
|
||||||
- [ ] Standardize event type definitions
|
- Unclear relationship between these two systems
|
||||||
|
|
||||||
- [ ] Test core module changes
|
2. **Mixed Concerns**:
|
||||||
- [ ] Run unit tests for core modules
|
- Port management is mixed with forwarding logic
|
||||||
- [ ] Verify type compatibility
|
- Domain routing is separated from port listening
|
||||||
- [ ] Ensure backward compatibility
|
- Security settings defined in multiple places
|
||||||
|
|
||||||
## Phase 3: Certificate Module Standardization
|
3. **Complex Logic**:
|
||||||
|
- PortRangeManager must coordinate with domain configuration
|
||||||
|
- Implicit rules for handling connections based on port and domain
|
||||||
|
|
||||||
- [ ] Update certificate interfaces
|
4. **Difficult to Understand and Configure**:
|
||||||
- [ ] Rename interfaces in `ts/certificate/models/certificate-types.ts`
|
- Two separate configuration hierarchies that must work together
|
||||||
- [ ] `CertificateData` → `ICertificateData`
|
- Unclear which settings take precedence
|
||||||
- [ ] `Certificates` → `ICertificates`
|
|
||||||
- [ ] `CertificateFailure` → `ICertificateFailure`
|
|
||||||
- [ ] `CertificateExpiring` → `ICertificateExpiring`
|
|
||||||
- [ ] `ForwardConfig` → `IForwardConfig`
|
|
||||||
- [ ] `DomainForwardConfig` → `IDomainForwardConfig`
|
|
||||||
- [ ] Update ACME challenge interfaces
|
|
||||||
- [ ] Standardize storage provider interfaces
|
|
||||||
|
|
||||||
- [ ] Ensure certificate provider compatibility
|
## Proposed Solution: Fully Unified Routing Configuration
|
||||||
- [ ] Update provider implementations
|
|
||||||
- [ ] Rename internal interfaces
|
|
||||||
- [ ] Maintain public API compatibility
|
|
||||||
|
|
||||||
- [ ] Test certificate module
|
Replace both port and domain configuration with a single, unified configuration:
|
||||||
- [ ] Verify ACME functionality
|
|
||||||
- [ ] Test certificate provisioning
|
|
||||||
- [ ] Validate challenge handling
|
|
||||||
|
|
||||||
## Phase 4: Forwarding System Standardization
|
```typescript
|
||||||
|
// The core unified configuration interface
|
||||||
|
interface IRouteConfig {
|
||||||
|
// What to match
|
||||||
|
match: {
|
||||||
|
// Listen on these ports (required)
|
||||||
|
ports: number | number[] | Array<{ from: number, to: number }>;
|
||||||
|
|
||||||
|
// Optional domain patterns to match (default: all domains)
|
||||||
|
domains?: string | string[];
|
||||||
|
|
||||||
|
// Advanced matching criteria
|
||||||
|
path?: string; // Match specific paths
|
||||||
|
clientIp?: string[]; // Match specific client IPs
|
||||||
|
tlsVersion?: string[]; // Match specific TLS versions
|
||||||
|
};
|
||||||
|
|
||||||
|
// What to do with matched traffic
|
||||||
|
action: {
|
||||||
|
// Basic routing
|
||||||
|
type: 'forward' | 'redirect' | 'block';
|
||||||
|
|
||||||
|
// Target for forwarding
|
||||||
|
target?: {
|
||||||
|
host: string | string[]; // Support single host or round-robin
|
||||||
|
port: number;
|
||||||
|
preservePort?: boolean; // Use incoming port as target port
|
||||||
|
};
|
||||||
|
|
||||||
|
// TLS handling
|
||||||
|
tls?: {
|
||||||
|
mode: 'passthrough' | 'terminate' | 'terminate-and-reencrypt';
|
||||||
|
certificate?: 'auto' | { // Auto = use ACME
|
||||||
|
key: string;
|
||||||
|
cert: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// For redirects
|
||||||
|
redirect?: {
|
||||||
|
to: string; // URL or template with {domain}, {port}, etc.
|
||||||
|
status: 301 | 302 | 307 | 308;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Security options
|
||||||
|
security?: {
|
||||||
|
allowedIps?: string[];
|
||||||
|
blockedIps?: string[];
|
||||||
|
maxConnections?: number;
|
||||||
|
authentication?: {
|
||||||
|
type: 'basic' | 'digest' | 'oauth';
|
||||||
|
// Auth-specific options
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Advanced options
|
||||||
|
advanced?: {
|
||||||
|
timeout?: number;
|
||||||
|
headers?: Record<string, string>;
|
||||||
|
keepAlive?: boolean;
|
||||||
|
// etc.
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Optional metadata
|
||||||
|
name?: string; // Human-readable name for this route
|
||||||
|
description?: string; // Description of the route's purpose
|
||||||
|
priority?: number; // Controls matching order (higher = matched first)
|
||||||
|
tags?: string[]; // Arbitrary tags for categorization
|
||||||
|
}
|
||||||
|
|
||||||
- [ ] Update forwarding configuration interfaces
|
// Main SmartProxy options
|
||||||
- [ ] Rename interfaces in `ts/forwarding/config/forwarding-types.ts`
|
interface ISmartProxyOptions {
|
||||||
- [ ] `TargetConfig` → `ITargetConfig`
|
// The unified configuration array (required)
|
||||||
- [ ] `HttpOptions` → `IHttpOptions`
|
routes: IRouteConfig[];
|
||||||
- [ ] `HttpsOptions` → `IHttpsOptions`
|
|
||||||
- [ ] `AcmeForwardingOptions` → `IAcmeForwardingOptions`
|
// Global/default settings
|
||||||
- [ ] `SecurityOptions` → `ISecurityOptions`
|
defaults?: {
|
||||||
- [ ] `AdvancedOptions` → `IAdvancedOptions`
|
target?: {
|
||||||
- [ ] `ForwardConfig` → `IForwardConfig`
|
host: string;
|
||||||
- [ ] Rename type definitions
|
port: number;
|
||||||
- [ ] `ForwardingType` → `TForwardingType`
|
};
|
||||||
- [ ] Update domain configuration interfaces
|
security?: {
|
||||||
|
// Global security defaults
|
||||||
|
};
|
||||||
|
tls?: {
|
||||||
|
// Global TLS defaults
|
||||||
|
};
|
||||||
|
// ...other defaults
|
||||||
|
};
|
||||||
|
|
||||||
|
// Other global settings remain (acme, etc.)
|
||||||
|
acme?: IAcmeOptions;
|
||||||
|
|
||||||
|
// Advanced settings remain as well
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
- [ ] Standardize handler interfaces
|
### Example Configuration
|
||||||
- [ ] Update base handler interfaces
|
|
||||||
- [ ] Rename handler-specific interfaces
|
|
||||||
- [ ] Update factory interfaces
|
|
||||||
|
|
||||||
- [ ] Verify forwarding system functionality
|
```typescript
|
||||||
- [ ] Test all forwarding types
|
const proxy = new SmartProxy({
|
||||||
- [ ] Verify configuration parsing
|
// All routing is configured in a single array
|
||||||
- [ ] Ensure backward compatibility
|
routes: [
|
||||||
|
// Basic HTTPS server with automatic certificates
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
ports: 443,
|
||||||
|
domains: ['example.com', '*.example.com']
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: {
|
||||||
|
host: 'localhost',
|
||||||
|
port: 8080
|
||||||
|
},
|
||||||
|
tls: {
|
||||||
|
mode: 'terminate',
|
||||||
|
certificate: 'auto' // Use ACME
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: 'Main HTTPS Server'
|
||||||
|
},
|
||||||
|
|
||||||
|
// HTTP to HTTPS redirect
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
ports: 80,
|
||||||
|
domains: ['example.com', '*.example.com']
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'redirect',
|
||||||
|
redirect: {
|
||||||
|
to: 'https://{domain}{path}',
|
||||||
|
status: 301
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: 'HTTP to HTTPS Redirect'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Admin portal with IP restriction
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
ports: 8443,
|
||||||
|
domains: 'admin.example.com'
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: {
|
||||||
|
host: 'admin-backend',
|
||||||
|
port: 3000
|
||||||
|
},
|
||||||
|
tls: {
|
||||||
|
mode: 'terminate',
|
||||||
|
certificate: 'auto'
|
||||||
|
},
|
||||||
|
security: {
|
||||||
|
allowedIps: ['192.168.1.*', '10.0.0.*'],
|
||||||
|
maxConnections: 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
priority: 100, // Higher priority than default rules
|
||||||
|
name: 'Admin Portal'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Port range for direct forwarding
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
ports: [{ from: 10000, to: 10010 }],
|
||||||
|
// No domains = all domains or direct IP
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: {
|
||||||
|
host: 'backend-server',
|
||||||
|
port: 10000,
|
||||||
|
preservePort: true // Use same port number as incoming
|
||||||
|
},
|
||||||
|
tls: {
|
||||||
|
mode: 'passthrough' // Direct TCP forwarding
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: 'Dynamic Port Range'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Path-based routing
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
ports: 443,
|
||||||
|
domains: 'api.example.com',
|
||||||
|
path: '/v1/*'
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: {
|
||||||
|
host: 'api-v1-service',
|
||||||
|
port: 8001
|
||||||
|
},
|
||||||
|
tls: {
|
||||||
|
mode: 'terminate'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: 'API v1 Endpoints'
|
||||||
|
},
|
||||||
|
|
||||||
|
// Load balanced backend
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
ports: 443,
|
||||||
|
domains: 'app.example.com'
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: {
|
||||||
|
// Round-robin load balancing
|
||||||
|
host: [
|
||||||
|
'app-server-1',
|
||||||
|
'app-server-2',
|
||||||
|
'app-server-3'
|
||||||
|
],
|
||||||
|
port: 8080
|
||||||
|
},
|
||||||
|
tls: {
|
||||||
|
mode: 'terminate'
|
||||||
|
},
|
||||||
|
advanced: {
|
||||||
|
headers: {
|
||||||
|
'X-Served-By': '{server}',
|
||||||
|
'X-Client-IP': '{clientIp}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: 'Load Balanced App Servers'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
// Global defaults
|
||||||
|
defaults: {
|
||||||
|
target: {
|
||||||
|
host: 'localhost',
|
||||||
|
port: 8080
|
||||||
|
},
|
||||||
|
security: {
|
||||||
|
maxConnections: 1000,
|
||||||
|
// Global security defaults
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// ACME configuration for auto certificates
|
||||||
|
acme: {
|
||||||
|
enabled: true,
|
||||||
|
email: 'admin@example.com',
|
||||||
|
production: true,
|
||||||
|
renewThresholdDays: 30
|
||||||
|
},
|
||||||
|
|
||||||
|
// Other global settings
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## Phase 5: Proxy Implementation Standardization
|
## Implementation Plan
|
||||||
|
|
||||||
- [ ] Update SmartProxy interfaces
|
### Phase 1: Core Design & Interface Definition
|
||||||
- [ ] Rename interfaces in `ts/proxies/smart-proxy/models/interfaces.ts`
|
|
||||||
- [ ] Update domain configuration interfaces
|
|
||||||
- [ ] Standardize manager interfaces
|
|
||||||
|
|
||||||
- [ ] Update NetworkProxy interfaces
|
1. **Define New Core Interfaces**:
|
||||||
- [ ] Rename in `ts/proxies/network-proxy/models/types.ts`
|
- Create `IRouteConfig` interface with `match` and `action` branches
|
||||||
- [ ] `NetworkProxyOptions` → `INetworkProxyOptions`
|
- Define all sub-interfaces for matching and actions
|
||||||
- [ ] `CertificateEntry` → `ICertificateEntry`
|
- Update `ISmartProxyOptions` to use `routes` array
|
||||||
- [ ] `ReverseProxyConfig` → `IReverseProxyConfig`
|
- Define template variable system for dynamic values
|
||||||
- [ ] `ConnectionEntry` → `IConnectionEntry`
|
|
||||||
- [ ] `WebSocketWithHeartbeat` → `IWebSocketWithHeartbeat`
|
|
||||||
- [ ] `Logger` → `ILogger`
|
|
||||||
- [ ] Update request handler interfaces
|
|
||||||
- [ ] Standardize connection interfaces
|
|
||||||
|
|
||||||
- [ ] Update NfTablesProxy interfaces
|
2. **Create Helper Functions**:
|
||||||
- [ ] Rename interfaces in `ts/proxies/nftables-proxy/models/interfaces.ts`
|
- `createRoute()` - Basic route creation with reasonable defaults
|
||||||
- [ ] Update configuration interfaces
|
- `createHttpRoute()`, `createHttpsRoute()`, `createRedirect()` - Common scenarios
|
||||||
- [ ] Standardize firewall rule interfaces
|
- `createLoadBalancer()` - For multi-target setups
|
||||||
|
- `mergeSecurity()`, `mergeDefaults()` - For combining configs
|
||||||
|
|
||||||
- [ ] Test proxy implementations
|
3. **Design Router**:
|
||||||
- [ ] Verify SmartProxy functionality
|
- Decision tree for route matching algorithm
|
||||||
- [ ] Test NetworkProxy with renamed interfaces
|
- Priority system for route ordering
|
||||||
- [ ] Validate NfTablesProxy operations
|
- Optimized lookup strategy for fast routing
|
||||||
|
|
||||||
## Phase 6: HTTP & TLS Module Standardization
|
### Phase 2: Core Implementation
|
||||||
|
|
||||||
- [ ] Update HTTP interfaces
|
1. **Create RouteManager**:
|
||||||
- [ ] Rename in `ts/http/port80/acme-interfaces.ts`
|
- Replaces both PortRangeManager and DomainConfigManager
|
||||||
- [ ] `SmartAcmeCert` → `ISmartAcmeCert`
|
- Handles all routing decisions in one place
|
||||||
- [ ] `SmartAcmeOptions` → `ISmartAcmeOptions`
|
- Provides fast lookup from port+domain+path to action
|
||||||
- [ ] `Http01Challenge` → `IHttp01Challenge`
|
- Manages server instances for different ports
|
||||||
- [ ] `SmartAcme` → `ISmartAcme`
|
|
||||||
- [ ] Standardize router interfaces
|
|
||||||
- [ ] Update port80 handler interfaces
|
|
||||||
- [ ] Update redirect interfaces
|
|
||||||
|
|
||||||
- [ ] Update TLS/SNI interfaces
|
2. **Update ConnectionHandler**:
|
||||||
- [ ] Standardize SNI handler interfaces
|
- Simplify to work with the unified route system
|
||||||
- [ ] Update client hello parser types
|
- Implement templating system for dynamic values
|
||||||
- [ ] Rename TLS alert interfaces
|
- Support more sophisticated routing rules
|
||||||
|
|
||||||
- [ ] Test HTTP & TLS functionality
|
3. **Implement New SmartProxy Core**:
|
||||||
- [ ] Verify router operation
|
- Rewrite initialization to use route-based configuration
|
||||||
- [ ] Test SNI extraction
|
- Create network servers based on port specifications
|
||||||
- [ ] Validate redirect functionality
|
- Manage TLS contexts and certificates
|
||||||
|
|
||||||
## Phase 7: Backward Compatibility Layer
|
### Phase 3: Feature Implementation
|
||||||
|
|
||||||
- [ ] Implement comprehensive type aliases
|
1. **Path-Based Routing**:
|
||||||
- [ ] Create aliases for all renamed interfaces
|
- Implement HTTP path matching
|
||||||
- [ ] Add deprecation notices via JSDoc
|
- Add wildcard and regex support for paths
|
||||||
- [ ] Ensure all exports include both named versions
|
- Create route differentiation based on HTTP method
|
||||||
|
|
||||||
- [ ] Update main entry point
|
2. **Enhanced Security**:
|
||||||
- [ ] Update `ts/index.ts` with all exports
|
- Implement per-route security rules
|
||||||
- [ ] Include both prefixed and non-prefixed names
|
- Add authentication methods (basic, digest, etc.)
|
||||||
- [ ] Organize exports by module
|
- Support for IP-based access control
|
||||||
|
|
||||||
- [ ] Add compatibility documentation
|
3. **TLS Management**:
|
||||||
- [ ] Document renaming strategy
|
- Support multiple certificate types (auto, manual, wildcard)
|
||||||
- [ ] Provide migration examples
|
- Implement certificate selection based on SNI
|
||||||
- [ ] Create deprecation timeline
|
- Support different TLS modes per route
|
||||||
|
|
||||||
## Phase 8: Documentation & Examples
|
4. **Metrics & Monitoring**:
|
||||||
|
- Per-route statistics
|
||||||
|
- Named route tracking for better visibility
|
||||||
|
- Tag-based grouping of metrics
|
||||||
|
|
||||||
- [ ] Update README and API documentation
|
### Phase 4: Backward Compatibility
|
||||||
- [ ] Update interface references in README.md
|
|
||||||
- [ ] Document naming convention in README.md
|
|
||||||
- [ ] Update API reference documentation
|
|
||||||
|
|
||||||
- [ ] Update examples
|
1. **Legacy Adapter Layer**:
|
||||||
- [ ] Modify example code to use new interface names
|
- Convert old configuration format to route-based format
|
||||||
- [ ] Add compatibility notes
|
- Map fromPort/toPort/domainConfigs to unified routes
|
||||||
- [ ] Create migration examples
|
- Preserve all functionality during migration
|
||||||
|
|
||||||
- [ ] Add contributor guidelines
|
2. **API Compatibility**:
|
||||||
- [ ] Document naming conventions
|
- Support both old and new configuration methods
|
||||||
- [ ] Add interface/type style guide
|
- Add deprecation warnings when using legacy properties
|
||||||
- [ ] Update PR templates
|
- Provide migration utilities
|
||||||
|
|
||||||
## Phase 9: Testing & Validation
|
3. **Documentation**:
|
||||||
|
- Clear migration guide for existing users
|
||||||
|
- Examples mapping old config to new config
|
||||||
|
- Timeline for deprecation
|
||||||
|
|
||||||
- [ ] Run comprehensive test suite
|
### Phase 5: Documentation & Examples
|
||||||
- [ ] Run all unit tests
|
|
||||||
- [ ] Execute integration tests
|
|
||||||
- [ ] Verify example code
|
|
||||||
|
|
||||||
- [ ] Build type declarations
|
1. **Update Core Documentation**:
|
||||||
- [ ] Generate TypeScript declaration files
|
- Rewrite README.md with a focus on route-based configuration
|
||||||
- [ ] Verify exported types
|
- Create interface reference documentation
|
||||||
- [ ] Validate documentation generation
|
- Document all template variables
|
||||||
|
|
||||||
- [ ] Final compatibility check
|
2. **Create Example Library**:
|
||||||
- [ ] Verify import compatibility
|
- Common configuration patterns
|
||||||
- [ ] Test with existing dependent projects
|
- Complex use cases for advanced features
|
||||||
- [ ] Validate backward compatibility claims
|
- Infrastructure-as-code examples
|
||||||
|
|
||||||
|
3. **Add Validation Tooling**:
|
||||||
|
- Configuration validator to check for issues
|
||||||
|
- Schema definitions for IDE autocomplete
|
||||||
|
- Runtime validation helpers
|
||||||
|
|
||||||
|
### Phase 6: Testing
|
||||||
|
|
||||||
|
1. **Unit Tests**:
|
||||||
|
- Test route matching logic
|
||||||
|
- Validate priority handling
|
||||||
|
- Test template processing
|
||||||
|
|
||||||
|
2. **Integration Tests**:
|
||||||
|
- Verify full proxy flows
|
||||||
|
- Test complex routing scenarios
|
||||||
|
- Check backward compatibility
|
||||||
|
|
||||||
|
3. **Performance Testing**:
|
||||||
|
- Benchmark routing performance
|
||||||
|
- Evaluate memory usage
|
||||||
|
- Test with large numbers of routes
|
||||||
|
|
||||||
|
## Benefits of the New Approach
|
||||||
|
|
||||||
|
1. **Truly Unified Configuration**:
|
||||||
|
- One "source of truth" for all routing
|
||||||
|
- Entire routing flow visible in a single configuration
|
||||||
|
- No overlapping or conflicting configuration systems
|
||||||
|
|
||||||
|
2. **Declarative Intent**:
|
||||||
|
- Configuration clearly states what to match and what action to take
|
||||||
|
- Metadata provides context and documentation inline
|
||||||
|
- Easy to understand the purpose of each route
|
||||||
|
|
||||||
|
3. **Advanced Routing Capabilities**:
|
||||||
|
- Path-based routing with pattern matching
|
||||||
|
- Client IP-based conditional routing
|
||||||
|
- Fine-grained security controls
|
||||||
|
|
||||||
|
4. **Composable and Extensible**:
|
||||||
|
- Each route is a self-contained unit of configuration
|
||||||
|
- Routes can be grouped by tags or priority
|
||||||
|
- New match criteria or actions can be added without breaking changes
|
||||||
|
|
||||||
|
5. **Better Developer Experience**:
|
||||||
|
- Clear, consistent configuration pattern
|
||||||
|
- Helper functions for common scenarios
|
||||||
|
- Better error messages and validation
|
||||||
|
|
||||||
|
## Example Use Cases
|
||||||
|
|
||||||
|
### 1. Complete Reverse Proxy with Auto SSL
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const proxy = new SmartProxy({
|
||||||
|
routes: [
|
||||||
|
// HTTPS server for all domains
|
||||||
|
{
|
||||||
|
match: { ports: 443 },
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: { host: 'localhost', port: 8080 },
|
||||||
|
tls: { mode: 'terminate', certificate: 'auto' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// HTTP to HTTPS redirect
|
||||||
|
{
|
||||||
|
match: { ports: 80 },
|
||||||
|
action: {
|
||||||
|
type: 'redirect',
|
||||||
|
redirect: { to: 'https://{domain}{path}', status: 301 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
acme: {
|
||||||
|
enabled: true,
|
||||||
|
email: 'admin@example.com',
|
||||||
|
production: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Microservices API Gateway
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const apiGateway = new SmartProxy({
|
||||||
|
routes: [
|
||||||
|
// Users API
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
ports: 443,
|
||||||
|
domains: 'api.example.com',
|
||||||
|
path: '/users/*'
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: { host: 'users-service', port: 8001 },
|
||||||
|
tls: { mode: 'terminate', certificate: 'auto' }
|
||||||
|
},
|
||||||
|
name: 'Users Service'
|
||||||
|
},
|
||||||
|
// Products API
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
ports: 443,
|
||||||
|
domains: 'api.example.com',
|
||||||
|
path: '/products/*'
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: { host: 'products-service', port: 8002 },
|
||||||
|
tls: { mode: 'terminate', certificate: 'auto' }
|
||||||
|
},
|
||||||
|
name: 'Products Service'
|
||||||
|
},
|
||||||
|
// Orders API with authentication
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
ports: 443,
|
||||||
|
domains: 'api.example.com',
|
||||||
|
path: '/orders/*'
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: { host: 'orders-service', port: 8003 },
|
||||||
|
tls: { mode: 'terminate', certificate: 'auto' },
|
||||||
|
security: {
|
||||||
|
authentication: {
|
||||||
|
type: 'basic',
|
||||||
|
users: { 'admin': 'password' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
name: 'Orders Service (Protected)'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
acme: {
|
||||||
|
enabled: true,
|
||||||
|
email: 'admin@example.com'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Multi-Environment Setup
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const environments = {
|
||||||
|
production: {
|
||||||
|
target: { host: 'prod-backend', port: 8080 },
|
||||||
|
security: { maxConnections: 1000 }
|
||||||
|
},
|
||||||
|
staging: {
|
||||||
|
target: { host: 'staging-backend', port: 8080 },
|
||||||
|
security: {
|
||||||
|
allowedIps: ['10.0.0.*', '192.168.1.*'],
|
||||||
|
maxConnections: 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
development: {
|
||||||
|
target: { host: 'localhost', port: 3000 },
|
||||||
|
security: {
|
||||||
|
allowedIps: ['127.0.0.1'],
|
||||||
|
maxConnections: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Select environment based on hostname
|
||||||
|
const proxy = new SmartProxy({
|
||||||
|
routes: [
|
||||||
|
// Production environment
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
ports: [80, 443],
|
||||||
|
domains: ['app.example.com', 'www.example.com']
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: environments.production.target,
|
||||||
|
tls: { mode: 'terminate', certificate: 'auto' },
|
||||||
|
security: environments.production.security
|
||||||
|
},
|
||||||
|
name: 'Production Environment'
|
||||||
|
},
|
||||||
|
// Staging environment
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
ports: [80, 443],
|
||||||
|
domains: 'staging.example.com'
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: environments.staging.target,
|
||||||
|
tls: { mode: 'terminate', certificate: 'auto' },
|
||||||
|
security: environments.staging.security
|
||||||
|
},
|
||||||
|
name: 'Staging Environment'
|
||||||
|
},
|
||||||
|
// Development environment
|
||||||
|
{
|
||||||
|
match: {
|
||||||
|
ports: [80, 443],
|
||||||
|
domains: 'dev.example.com'
|
||||||
|
},
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: environments.development.target,
|
||||||
|
tls: { mode: 'terminate', certificate: 'auto' },
|
||||||
|
security: environments.development.security
|
||||||
|
},
|
||||||
|
name: 'Development Environment'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
acme: { enabled: true, email: 'admin@example.com' }
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
## Implementation Strategy
|
## Implementation Strategy
|
||||||
|
|
||||||
### Naming Pattern Rules
|
### Code Organization
|
||||||
|
|
||||||
1. **Interfaces**:
|
1. **New Files**:
|
||||||
- All interfaces should be prefixed with "I"
|
- `route-manager.ts` (core routing engine)
|
||||||
- Example: `DomainConfig` → `IDomainConfig`
|
- `route-types.ts` (interface definitions)
|
||||||
|
- `route-helpers.ts` (helper functions)
|
||||||
|
- `route-matcher.ts` (matching logic)
|
||||||
|
- `template-engine.ts` (for variable substitution)
|
||||||
|
|
||||||
2. **Type Aliases**:
|
2. **Modified Files**:
|
||||||
- All type aliases should be prefixed with "T"
|
- `smart-proxy.ts` (update to use route-based configuration)
|
||||||
- Example: `ForwardingType` → `TForwardingType`
|
- `connection-handler.ts` (simplify using route-based approach)
|
||||||
|
- Replace `port-range-manager.ts` and `domain-config-manager.ts`
|
||||||
|
|
||||||
3. **Enums**:
|
### Backward Compatibility
|
||||||
- Enums should be named in PascalCase without prefix
|
|
||||||
- Example: `CertificateSource`
|
|
||||||
|
|
||||||
4. **Backward Compatibility**:
|
The backward compatibility layer will convert the legacy configuration to the new format:
|
||||||
- No Backward compatibility. Remove old names.
|
|
||||||
|
|
||||||
### Module Implementation Order
|
```typescript
|
||||||
|
function convertLegacyConfig(legacy: ILegacySmartProxyOptions): ISmartProxyOptions {
|
||||||
1. Core module
|
const routes: IRouteConfig[] = [];
|
||||||
2. Certificate module
|
|
||||||
3. Forwarding module
|
// Convert main port configuration
|
||||||
4. Proxy implementations
|
if (legacy.fromPort) {
|
||||||
5. HTTP & TLS modules
|
// Add main listener for fromPort
|
||||||
6. Main exports and entry points
|
routes.push({
|
||||||
|
match: { ports: legacy.fromPort },
|
||||||
### Testing Strategy
|
action: {
|
||||||
|
type: 'forward',
|
||||||
For each module:
|
target: { host: legacy.targetIP || 'localhost', port: legacy.toPort },
|
||||||
1. Rename interfaces and types
|
tls: { mode: legacy.sniEnabled ? 'passthrough' : 'terminate' }
|
||||||
2. Add backward compatibility aliases
|
},
|
||||||
3. Update imports throughout the module
|
name: 'Main Listener (Legacy)'
|
||||||
4. Run tests to verify functionality
|
});
|
||||||
5. Commit changes module by module
|
|
||||||
|
// If ACME is enabled, add HTTP listener for challenges
|
||||||
## File-Specific Changes
|
if (legacy.acme?.enabled) {
|
||||||
|
routes.push({
|
||||||
### Core Module Files
|
match: { ports: 80 },
|
||||||
- `ts/core/models/common-types.ts` - Primary interfaces
|
action: {
|
||||||
- `ts/core/utils/validation-utils.ts` - Validation type definitions
|
type: 'forward',
|
||||||
- `ts/core/utils/ip-utils.ts` - IP utility type definitions
|
target: { host: 'localhost', port: 80 },
|
||||||
- `ts/core/utils/event-utils.ts` - Event type definitions
|
// Special flag for ACME handler
|
||||||
|
acmeEnabled: true
|
||||||
### Certificate Module Files
|
},
|
||||||
- `ts/certificate/models/certificate-types.ts` - Certificate interfaces
|
name: 'ACME Challenge Handler (Legacy)'
|
||||||
- `ts/certificate/acme/acme-factory.ts` - ACME factory types
|
});
|
||||||
- `ts/certificate/providers/cert-provisioner.ts` - Provider interfaces
|
}
|
||||||
- `ts/certificate/storage/file-storage.ts` - Storage interfaces
|
}
|
||||||
|
|
||||||
### Forwarding Module Files
|
// Convert domain configs
|
||||||
- `ts/forwarding/config/forwarding-types.ts` - Forwarding interfaces and types
|
if (legacy.domainConfigs) {
|
||||||
- `ts/forwarding/config/domain-config.ts` - Domain configuration
|
for (const domainConfig of legacy.domainConfigs) {
|
||||||
- `ts/forwarding/factory/forwarding-factory.ts` - Factory interfaces
|
const { domains, forwarding } = domainConfig;
|
||||||
- `ts/forwarding/handlers/*.ts` - Handler interfaces
|
|
||||||
|
// Determine action based on forwarding type
|
||||||
### Proxy Module Files
|
let action: Partial<IRouteAction> = {
|
||||||
- `ts/proxies/network-proxy/models/types.ts` - NetworkProxy interfaces
|
type: 'forward',
|
||||||
- `ts/proxies/smart-proxy/models/interfaces.ts` - SmartProxy interfaces
|
target: {
|
||||||
- `ts/proxies/nftables-proxy/models/interfaces.ts` - NfTables interfaces
|
host: forwarding.target.host,
|
||||||
- `ts/proxies/smart-proxy/connection-manager.ts` - Connection types
|
port: forwarding.target.port
|
||||||
|
}
|
||||||
### HTTP/TLS Module Files
|
};
|
||||||
- `ts/http/models/http-types.ts` - HTTP module interfaces
|
|
||||||
- `ts/http/port80/acme-interfaces.ts` - ACME interfaces
|
// Set TLS mode based on forwarding type
|
||||||
- `ts/tls/sni/client-hello-parser.ts` - TLS parser types
|
switch (forwarding.type) {
|
||||||
- `ts/tls/alerts/tls-alert.ts` - TLS alert interfaces
|
case 'http-only':
|
||||||
|
// No TLS
|
||||||
|
break;
|
||||||
|
case 'https-passthrough':
|
||||||
|
action.tls = { mode: 'passthrough' };
|
||||||
|
break;
|
||||||
|
case 'https-terminate-to-http':
|
||||||
|
action.tls = {
|
||||||
|
mode: 'terminate',
|
||||||
|
certificate: forwarding.https?.customCert || 'auto'
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
case 'https-terminate-to-https':
|
||||||
|
action.tls = {
|
||||||
|
mode: 'terminate-and-reencrypt',
|
||||||
|
certificate: forwarding.https?.customCert || 'auto'
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Security settings
|
||||||
|
if (forwarding.security) {
|
||||||
|
action.security = forwarding.security;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add HTTP redirect if needed
|
||||||
|
if (forwarding.http?.redirectToHttps) {
|
||||||
|
routes.push({
|
||||||
|
match: { ports: 80, domains },
|
||||||
|
action: {
|
||||||
|
type: 'redirect',
|
||||||
|
redirect: { to: 'https://{domain}{path}', status: 301 }
|
||||||
|
},
|
||||||
|
name: `HTTP Redirect for ${domains.join(', ')} (Legacy)`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add main route
|
||||||
|
routes.push({
|
||||||
|
match: {
|
||||||
|
ports: forwarding.type.startsWith('https') ? 443 : 80,
|
||||||
|
domains
|
||||||
|
},
|
||||||
|
action: action as IRouteAction,
|
||||||
|
name: `Route for ${domains.join(', ')} (Legacy)`
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add port ranges if specified
|
||||||
|
if (forwarding.advanced?.portRanges) {
|
||||||
|
for (const range of forwarding.advanced.portRanges) {
|
||||||
|
routes.push({
|
||||||
|
match: {
|
||||||
|
ports: { from: range.from, to: range.to },
|
||||||
|
domains
|
||||||
|
},
|
||||||
|
action: action as IRouteAction,
|
||||||
|
name: `Port Range ${range.from}-${range.to} for ${domains.join(', ')} (Legacy)`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Global port ranges
|
||||||
|
if (legacy.globalPortRanges) {
|
||||||
|
for (const range of legacy.globalPortRanges) {
|
||||||
|
routes.push({
|
||||||
|
match: { ports: { from: range.from, to: range.to } },
|
||||||
|
action: {
|
||||||
|
type: 'forward',
|
||||||
|
target: {
|
||||||
|
host: legacy.targetIP || 'localhost',
|
||||||
|
port: legacy.forwardAllGlobalRanges ? 0 : legacy.toPort,
|
||||||
|
preservePort: !!legacy.forwardAllGlobalRanges
|
||||||
|
},
|
||||||
|
tls: { mode: 'passthrough' }
|
||||||
|
},
|
||||||
|
name: `Global Port Range ${range.from}-${range.to} (Legacy)`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
routes,
|
||||||
|
defaults: {
|
||||||
|
target: {
|
||||||
|
host: legacy.targetIP || 'localhost',
|
||||||
|
port: legacy.toPort
|
||||||
|
}
|
||||||
|
},
|
||||||
|
acme: legacy.acme
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Success Criteria
|
## Success Criteria
|
||||||
|
|
||||||
- All interfaces are prefixed with "I"
|
- All existing functionality works with the new route-based configuration
|
||||||
- All type aliases are prefixed with "T"
|
- Performance is equal or better than the current implementation
|
||||||
- All tests pass with new naming conventions
|
- Configuration is more intuitive and easier to understand
|
||||||
- Documentation is updated with new naming conventions
|
- New features can be added without breaking existing code
|
||||||
- Backward compatibility is maintained through type aliases
|
- Code is more maintainable with clear separation of concerns
|
||||||
- Declaration files correctly export both naming conventions
|
- Migration from old configuration to new is straightforward
|
Loading…
x
Reference in New Issue
Block a user