@push.rocks/smartproxy 21.1.7 → 22.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/changelog.md +109 -0
  2. package/dist_rust/rustproxy +0 -0
  3. package/dist_ts/00_commitinfo_data.js +1 -1
  4. package/dist_ts/core/utils/shared-security-manager.d.ts +17 -0
  5. package/dist_ts/core/utils/shared-security-manager.js +66 -1
  6. package/dist_ts/index.d.ts +1 -5
  7. package/dist_ts/index.js +3 -9
  8. package/dist_ts/protocols/common/fragment-handler.js +5 -1
  9. package/dist_ts/proxies/http-proxy/default-certificates.d.ts +54 -0
  10. package/dist_ts/proxies/http-proxy/default-certificates.js +127 -0
  11. package/dist_ts/proxies/http-proxy/http-proxy.d.ts +1 -1
  12. package/dist_ts/proxies/http-proxy/http-proxy.js +9 -14
  13. package/dist_ts/proxies/http-proxy/index.d.ts +5 -1
  14. package/dist_ts/proxies/http-proxy/index.js +6 -2
  15. package/dist_ts/proxies/http-proxy/security-manager.d.ts +4 -12
  16. package/dist_ts/proxies/http-proxy/security-manager.js +66 -99
  17. package/dist_ts/proxies/index.d.ts +1 -5
  18. package/dist_ts/proxies/index.js +2 -6
  19. package/dist_ts/proxies/nftables-proxy/index.d.ts +1 -0
  20. package/dist_ts/proxies/nftables-proxy/index.js +2 -1
  21. package/dist_ts/proxies/nftables-proxy/nftables-proxy.d.ts +4 -26
  22. package/dist_ts/proxies/nftables-proxy/nftables-proxy.js +84 -236
  23. package/dist_ts/proxies/nftables-proxy/utils/index.d.ts +9 -0
  24. package/dist_ts/proxies/nftables-proxy/utils/index.js +12 -0
  25. package/dist_ts/proxies/nftables-proxy/utils/nft-command-executor.d.ts +66 -0
  26. package/dist_ts/proxies/nftables-proxy/utils/nft-command-executor.js +131 -0
  27. package/dist_ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.d.ts +39 -0
  28. package/dist_ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.js +112 -0
  29. package/dist_ts/proxies/nftables-proxy/utils/nft-rule-validator.d.ts +59 -0
  30. package/dist_ts/proxies/nftables-proxy/utils/nft-rule-validator.js +130 -0
  31. package/dist_ts/proxies/smart-proxy/certificate-manager.js +4 -3
  32. package/dist_ts/proxies/smart-proxy/connection-manager.d.ts +13 -2
  33. package/dist_ts/proxies/smart-proxy/connection-manager.js +16 -6
  34. package/dist_ts/proxies/smart-proxy/http-proxy-bridge.js +35 -10
  35. package/dist_ts/proxies/smart-proxy/index.d.ts +5 -10
  36. package/dist_ts/proxies/smart-proxy/index.js +7 -13
  37. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +5 -3
  38. package/dist_ts/proxies/smart-proxy/route-connection-handler.d.ts +17 -0
  39. package/dist_ts/proxies/smart-proxy/route-connection-handler.js +72 -9
  40. package/dist_ts/proxies/smart-proxy/route-preprocessor.d.ts +37 -0
  41. package/dist_ts/proxies/smart-proxy/route-preprocessor.js +103 -0
  42. package/dist_ts/proxies/smart-proxy/rust-binary-locator.d.ts +23 -0
  43. package/dist_ts/proxies/smart-proxy/rust-binary-locator.js +104 -0
  44. package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.d.ts +74 -0
  45. package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.js +146 -0
  46. package/dist_ts/proxies/smart-proxy/rust-proxy-bridge.d.ts +49 -0
  47. package/dist_ts/proxies/smart-proxy/rust-proxy-bridge.js +259 -0
  48. package/dist_ts/proxies/smart-proxy/security-manager.d.ts +14 -12
  49. package/dist_ts/proxies/smart-proxy/security-manager.js +80 -74
  50. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +39 -157
  51. package/dist_ts/proxies/smart-proxy/smart-proxy.js +224 -622
  52. package/dist_ts/proxies/smart-proxy/socket-handler-server.d.ts +45 -0
  53. package/dist_ts/proxies/smart-proxy/socket-handler-server.js +253 -0
  54. package/dist_ts/proxies/smart-proxy/tls-manager.d.ts +2 -9
  55. package/dist_ts/proxies/smart-proxy/tls-manager.js +3 -26
  56. package/dist_ts/proxies/smart-proxy/utils/index.d.ts +1 -1
  57. package/dist_ts/proxies/smart-proxy/utils/index.js +3 -4
  58. package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.d.ts +49 -0
  59. package/dist_ts/proxies/smart-proxy/utils/route-helpers/api-helpers.js +108 -0
  60. package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.d.ts +57 -0
  61. package/dist_ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.js +89 -0
  62. package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.d.ts +17 -0
  63. package/dist_ts/proxies/smart-proxy/utils/route-helpers/http-helpers.js +32 -0
  64. package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.d.ts +68 -0
  65. package/dist_ts/proxies/smart-proxy/utils/route-helpers/https-helpers.js +117 -0
  66. package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.d.ts +17 -0
  67. package/dist_ts/proxies/smart-proxy/utils/route-helpers/index.js +27 -0
  68. package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.d.ts +63 -0
  69. package/dist_ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.js +105 -0
  70. package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.d.ts +83 -0
  71. package/dist_ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.js +126 -0
  72. package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.d.ts +47 -0
  73. package/dist_ts/proxies/smart-proxy/utils/route-helpers/security-helpers.js +66 -0
  74. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.d.ts +70 -0
  75. package/dist_ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.js +287 -0
  76. package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.d.ts +46 -0
  77. package/dist_ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.js +67 -0
  78. package/dist_ts/proxies/smart-proxy/utils/route-helpers.d.ts +4 -457
  79. package/dist_ts/proxies/smart-proxy/utils/route-helpers.js +6 -950
  80. package/dist_ts/proxies/smart-proxy/utils/route-utils.js +2 -2
  81. package/dist_ts/proxies/smart-proxy/utils/route-validator.d.ts +67 -1
  82. package/dist_ts/proxies/smart-proxy/utils/route-validator.js +251 -3
  83. package/dist_ts/routing/index.d.ts +1 -1
  84. package/dist_ts/routing/index.js +3 -3
  85. package/dist_ts/routing/models/http-types.d.ts +119 -4
  86. package/dist_ts/routing/models/http-types.js +93 -5
  87. package/npmextra.json +12 -6
  88. package/package.json +34 -24
  89. package/readme.hints.md +184 -1
  90. package/readme.md +580 -266
  91. package/ts/00_commitinfo_data.ts +1 -1
  92. package/ts/core/utils/shared-security-manager.ts +98 -13
  93. package/ts/index.ts +4 -12
  94. package/ts/protocols/common/fragment-handler.ts +4 -0
  95. package/ts/proxies/index.ts +1 -9
  96. package/ts/proxies/nftables-proxy/index.ts +1 -0
  97. package/ts/proxies/nftables-proxy/nftables-proxy.ts +116 -290
  98. package/ts/proxies/nftables-proxy/utils/index.ts +38 -0
  99. package/ts/proxies/nftables-proxy/utils/nft-command-executor.ts +162 -0
  100. package/ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.ts +125 -0
  101. package/ts/proxies/nftables-proxy/utils/nft-rule-validator.ts +156 -0
  102. package/ts/proxies/smart-proxy/index.ts +6 -13
  103. package/ts/proxies/smart-proxy/models/interfaces.ts +6 -5
  104. package/ts/proxies/smart-proxy/route-preprocessor.ts +122 -0
  105. package/ts/proxies/smart-proxy/rust-binary-locator.ts +112 -0
  106. package/ts/proxies/smart-proxy/rust-metrics-adapter.ts +161 -0
  107. package/ts/proxies/smart-proxy/rust-proxy-bridge.ts +310 -0
  108. package/ts/proxies/smart-proxy/smart-proxy.ts +282 -800
  109. package/ts/proxies/smart-proxy/socket-handler-server.ts +279 -0
  110. package/ts/proxies/smart-proxy/utils/index.ts +3 -5
  111. package/ts/proxies/smart-proxy/utils/route-helpers/api-helpers.ts +144 -0
  112. package/ts/proxies/smart-proxy/utils/route-helpers/dynamic-helpers.ts +124 -0
  113. package/ts/proxies/smart-proxy/utils/route-helpers/http-helpers.ts +40 -0
  114. package/ts/proxies/smart-proxy/utils/route-helpers/https-helpers.ts +163 -0
  115. package/ts/proxies/smart-proxy/utils/route-helpers/index.ts +62 -0
  116. package/ts/proxies/smart-proxy/utils/route-helpers/load-balancer-helpers.ts +154 -0
  117. package/ts/proxies/smart-proxy/utils/route-helpers/nftables-helpers.ts +202 -0
  118. package/ts/proxies/smart-proxy/utils/route-helpers/security-helpers.ts +96 -0
  119. package/ts/proxies/smart-proxy/utils/route-helpers/socket-handlers.ts +337 -0
  120. package/ts/proxies/smart-proxy/utils/route-helpers/websocket-helpers.ts +98 -0
  121. package/ts/proxies/smart-proxy/utils/route-helpers.ts +5 -1302
  122. package/ts/proxies/smart-proxy/utils/route-utils.ts +1 -1
  123. package/ts/proxies/smart-proxy/utils/route-validator.ts +274 -4
  124. package/ts/routing/index.ts +2 -2
  125. package/ts/routing/models/http-types.ts +147 -4
  126. package/ts/proxies/http-proxy/certificate-manager.ts +0 -244
  127. package/ts/proxies/http-proxy/connection-pool.ts +0 -228
  128. package/ts/proxies/http-proxy/context-creator.ts +0 -145
  129. package/ts/proxies/http-proxy/function-cache.ts +0 -279
  130. package/ts/proxies/http-proxy/handlers/index.ts +0 -5
  131. package/ts/proxies/http-proxy/http-proxy.ts +0 -675
  132. package/ts/proxies/http-proxy/http-request-handler.ts +0 -331
  133. package/ts/proxies/http-proxy/http2-request-handler.ts +0 -255
  134. package/ts/proxies/http-proxy/index.ts +0 -13
  135. package/ts/proxies/http-proxy/models/http-types.ts +0 -148
  136. package/ts/proxies/http-proxy/models/index.ts +0 -5
  137. package/ts/proxies/http-proxy/models/types.ts +0 -125
  138. package/ts/proxies/http-proxy/request-handler.ts +0 -878
  139. package/ts/proxies/http-proxy/security-manager.ts +0 -433
  140. package/ts/proxies/http-proxy/websocket-handler.ts +0 -581
  141. package/ts/proxies/smart-proxy/acme-state-manager.ts +0 -112
  142. package/ts/proxies/smart-proxy/cert-store.ts +0 -92
  143. package/ts/proxies/smart-proxy/certificate-manager.ts +0 -894
  144. package/ts/proxies/smart-proxy/connection-manager.ts +0 -796
  145. package/ts/proxies/smart-proxy/http-proxy-bridge.ts +0 -187
  146. package/ts/proxies/smart-proxy/metrics-collector.ts +0 -453
  147. package/ts/proxies/smart-proxy/nftables-manager.ts +0 -271
  148. package/ts/proxies/smart-proxy/port-manager.ts +0 -358
  149. package/ts/proxies/smart-proxy/route-connection-handler.ts +0 -1640
  150. package/ts/proxies/smart-proxy/route-orchestrator.ts +0 -297
  151. package/ts/proxies/smart-proxy/security-manager.ts +0 -257
  152. package/ts/proxies/smart-proxy/throughput-tracker.ts +0 -138
  153. package/ts/proxies/smart-proxy/timeout-manager.ts +0 -196
  154. package/ts/proxies/smart-proxy/tls-manager.ts +0 -207
  155. package/ts/proxies/smart-proxy/utils/route-validators.ts +0 -283
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import type { IRouteConfig, IRouteMatch } from '../models/route-types.js';
9
- import { validateRouteConfig } from './route-validators.js';
9
+ import { validateRouteConfig } from './route-validator.js';
10
10
 
11
11
  /**
12
12
  * Merge two route configurations
@@ -1,5 +1,5 @@
1
1
  import { logger } from '../../../core/utils/logger.js';
2
- import type { IRouteConfig } from '../models/route-types.js';
2
+ import type { IRouteConfig, IRouteMatch, IRouteAction, TPortRange } from '../models/route-types.js';
3
3
 
4
4
  /**
5
5
  * Validates route configurations for correctness and safety
@@ -439,8 +439,8 @@ export class RouteValidator {
439
439
  * Validate IPv6 address
440
440
  */
441
441
  private static isValidIPv6(ip: string): boolean {
442
- // Simple IPv6 validation
443
- const ipv6Pattern = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|::[0-9a-fA-F]{0,4}(:[0-9a-fA-F]{1,4}){0,6}|::1|::)$/;
442
+ // IPv6 validation including IPv6-mapped IPv4 addresses (::ffff:x.x.x.x)
443
+ const ipv6Pattern = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|::[0-9a-fA-F]{0,4}(:[0-9a-fA-F]{1,4}){0,6}|::1|::|::ffff:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i;
444
444
  return ipv6Pattern.test(ip);
445
445
  }
446
446
 
@@ -454,7 +454,7 @@ export class RouteValidator {
454
454
  errors: routeErrors,
455
455
  component: 'route-validator'
456
456
  });
457
-
457
+
458
458
  for (const error of routeErrors) {
459
459
  logger.log('error', ` - ${error}`, {
460
460
  route: routeName,
@@ -463,4 +463,274 @@ export class RouteValidator {
463
463
  }
464
464
  }
465
465
  }
466
+ }
467
+
468
+ // ============================================================================
469
+ // Functional API (for backwards compatibility with route-validators.ts)
470
+ // ============================================================================
471
+
472
+ /**
473
+ * Validates a port range or port number
474
+ * @param port Port number, port range, or port function
475
+ * @returns True if valid, false otherwise
476
+ */
477
+ export function isValidPort(port: any): boolean {
478
+ if (typeof port === 'number') {
479
+ return port > 0 && port < 65536;
480
+ } else if (Array.isArray(port)) {
481
+ return port.every(p =>
482
+ (typeof p === 'number' && p > 0 && p < 65536) ||
483
+ (typeof p === 'object' && 'from' in p && 'to' in p &&
484
+ p.from > 0 && p.from < 65536 && p.to > 0 && p.to < 65536)
485
+ );
486
+ } else if (typeof port === 'function') {
487
+ return true;
488
+ } else if (typeof port === 'object' && 'from' in port && 'to' in port) {
489
+ return port.from > 0 && port.from < 65536 && port.to > 0 && port.to < 65536;
490
+ }
491
+ return false;
492
+ }
493
+
494
+ /**
495
+ * Validates a domain string - supports wildcards, localhost, and IP addresses
496
+ * @param domain Domain string to validate
497
+ * @returns True if valid, false otherwise
498
+ */
499
+ export function isValidDomain(domain: string): boolean {
500
+ if (!domain || typeof domain !== 'string') return false;
501
+ if (domain === '*') return true;
502
+ if (domain === 'localhost') return true;
503
+
504
+ const domainPatterns = [
505
+ // Standard domain with optional wildcard subdomain (*.example.com)
506
+ /^(\*\.)?([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/,
507
+ // Wildcard prefix without dot (*example.com)
508
+ /^\*[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?))*$/,
509
+ // IP address
510
+ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,
511
+ // IPv6 address
512
+ /^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$/
513
+ ];
514
+
515
+ return domainPatterns.some(pattern => pattern.test(domain));
516
+ }
517
+
518
+ /**
519
+ * Validates a route match configuration
520
+ * @param match Route match configuration to validate
521
+ * @returns { valid: boolean, errors: string[] } Validation result
522
+ */
523
+ export function validateRouteMatch(match: IRouteMatch): { valid: boolean; errors: string[] } {
524
+ const errors: string[] = [];
525
+
526
+ if (match.ports !== undefined) {
527
+ if (!isValidPort(match.ports)) {
528
+ errors.push('Invalid port number or port range in match.ports');
529
+ }
530
+ }
531
+
532
+ if (match.domains !== undefined) {
533
+ if (typeof match.domains === 'string') {
534
+ if (!isValidDomain(match.domains)) {
535
+ errors.push(`Invalid domain format: ${match.domains}`);
536
+ }
537
+ } else if (Array.isArray(match.domains)) {
538
+ for (const domain of match.domains) {
539
+ if (!isValidDomain(domain)) {
540
+ errors.push(`Invalid domain format: ${domain}`);
541
+ }
542
+ }
543
+ } else {
544
+ errors.push('Domains must be a string or an array of strings');
545
+ }
546
+ }
547
+
548
+ if (match.path !== undefined) {
549
+ if (typeof match.path !== 'string' || !match.path.startsWith('/')) {
550
+ errors.push('Path must be a string starting with /');
551
+ }
552
+ }
553
+
554
+ return {
555
+ valid: errors.length === 0,
556
+ errors
557
+ };
558
+ }
559
+
560
+ /**
561
+ * Validates a route action configuration
562
+ * @param action Route action configuration to validate
563
+ * @returns { valid: boolean, errors: string[] } Validation result
564
+ */
565
+ export function validateRouteAction(action: IRouteAction): { valid: boolean; errors: string[] } {
566
+ const errors: string[] = [];
567
+
568
+ if (!action.type) {
569
+ errors.push('Action type is required');
570
+ } else if (!['forward', 'socket-handler'].includes(action.type)) {
571
+ errors.push(`Invalid action type: ${action.type}`);
572
+ }
573
+
574
+ if (action.type === 'forward') {
575
+ if (!action.targets || !Array.isArray(action.targets) || action.targets.length === 0) {
576
+ errors.push('Targets array is required for forward action');
577
+ } else {
578
+ action.targets.forEach((target, index) => {
579
+ if (!target.host) {
580
+ errors.push(`Target[${index}] host is required`);
581
+ } else if (typeof target.host !== 'string' &&
582
+ !Array.isArray(target.host) &&
583
+ typeof target.host !== 'function') {
584
+ errors.push(`Target[${index}] host must be a string, array of strings, or function`);
585
+ }
586
+
587
+ if (target.port === undefined) {
588
+ errors.push(`Target[${index}] port is required`);
589
+ } else if (typeof target.port !== 'number' &&
590
+ typeof target.port !== 'function' &&
591
+ target.port !== 'preserve') {
592
+ errors.push(`Target[${index}] port must be a number, 'preserve', or a function`);
593
+ } else if (typeof target.port === 'number' && !isValidPort(target.port)) {
594
+ errors.push(`Target[${index}] port must be between 1 and 65535`);
595
+ }
596
+
597
+ if (target.match) {
598
+ if (target.match.ports && !Array.isArray(target.match.ports)) {
599
+ errors.push(`Target[${index}] match.ports must be an array`);
600
+ }
601
+ if (target.match.method && !Array.isArray(target.match.method)) {
602
+ errors.push(`Target[${index}] match.method must be an array`);
603
+ }
604
+ }
605
+ });
606
+ }
607
+
608
+ if (action.tls) {
609
+ if (!['passthrough', 'terminate', 'terminate-and-reencrypt'].includes(action.tls.mode)) {
610
+ errors.push(`Invalid TLS mode: ${action.tls.mode}`);
611
+ }
612
+
613
+ if (['terminate', 'terminate-and-reencrypt'].includes(action.tls.mode)) {
614
+ if (action.tls.certificate !== 'auto' &&
615
+ (!action.tls.certificate || !action.tls.certificate.key || !action.tls.certificate.cert)) {
616
+ errors.push('Certificate must be "auto" or an object with key and cert properties');
617
+ }
618
+ }
619
+ }
620
+ }
621
+
622
+ if (action.type === 'socket-handler') {
623
+ if (!action.socketHandler) {
624
+ errors.push('Socket handler function is required for socket-handler action');
625
+ } else if (typeof action.socketHandler !== 'function') {
626
+ errors.push('Socket handler must be a function');
627
+ }
628
+ }
629
+
630
+ return {
631
+ valid: errors.length === 0,
632
+ errors
633
+ };
634
+ }
635
+
636
+ /**
637
+ * Validates a complete route configuration
638
+ * @param route Route configuration to validate
639
+ * @returns { valid: boolean, errors: string[] } Validation result
640
+ */
641
+ export function validateRouteConfig(route: IRouteConfig): { valid: boolean; errors: string[] } {
642
+ const errors: string[] = [];
643
+
644
+ if (!route.match) {
645
+ errors.push('Route match configuration is required');
646
+ }
647
+
648
+ if (!route.action) {
649
+ errors.push('Route action configuration is required');
650
+ }
651
+
652
+ if (route.match) {
653
+ const matchValidation = validateRouteMatch(route.match);
654
+ if (!matchValidation.valid) {
655
+ errors.push(...matchValidation.errors.map(err => `Match: ${err}`));
656
+ }
657
+ }
658
+
659
+ if (route.action) {
660
+ const actionValidation = validateRouteAction(route.action);
661
+ if (!actionValidation.valid) {
662
+ errors.push(...actionValidation.errors.map(err => `Action: ${err}`));
663
+ }
664
+ }
665
+
666
+ return {
667
+ valid: errors.length === 0,
668
+ errors
669
+ };
670
+ }
671
+
672
+ /**
673
+ * Validate an array of route configurations
674
+ * @param routes Array of route configurations to validate
675
+ * @returns { valid: boolean, errors: { index: number, errors: string[] }[] } Validation result
676
+ */
677
+ export function validateRoutes(routes: IRouteConfig[]): {
678
+ valid: boolean;
679
+ errors: { index: number; errors: string[] }[]
680
+ } {
681
+ const results: { index: number; errors: string[] }[] = [];
682
+
683
+ routes.forEach((route, index) => {
684
+ const validation = validateRouteConfig(route);
685
+ if (!validation.valid) {
686
+ results.push({
687
+ index,
688
+ errors: validation.errors
689
+ });
690
+ }
691
+ });
692
+
693
+ return {
694
+ valid: results.length === 0,
695
+ errors: results
696
+ };
697
+ }
698
+
699
+ /**
700
+ * Check if a route configuration has the required properties for a specific action type
701
+ * @param route Route configuration to check
702
+ * @param actionType Expected action type
703
+ * @returns True if the route has the necessary properties, false otherwise
704
+ */
705
+ export function hasRequiredPropertiesForAction(route: IRouteConfig, actionType: string): boolean {
706
+ if (!route.action || route.action.type !== actionType) {
707
+ return false;
708
+ }
709
+
710
+ switch (actionType) {
711
+ case 'forward':
712
+ return !!route.action.targets &&
713
+ Array.isArray(route.action.targets) &&
714
+ route.action.targets.length > 0 &&
715
+ route.action.targets.every(t => t.host && t.port !== undefined);
716
+ case 'socket-handler':
717
+ return !!route.action.socketHandler && typeof route.action.socketHandler === 'function';
718
+ default:
719
+ return false;
720
+ }
721
+ }
722
+
723
+ /**
724
+ * Throws an error if the route config is invalid, returns the config if valid
725
+ * Useful for immediate validation when creating routes
726
+ * @param route Route configuration to validate
727
+ * @returns The validated route configuration
728
+ * @throws Error if the route configuration is invalid
729
+ */
730
+ export function assertValidRoute(route: IRouteConfig): IRouteConfig {
731
+ const validation = validateRouteConfig(route);
732
+ if (!validation.valid) {
733
+ throw new Error(`Invalid route configuration: ${validation.errors.join(', ')}`);
734
+ }
735
+ return route;
466
736
  }
@@ -2,8 +2,8 @@
2
2
  * Routing functionality module
3
3
  */
4
4
 
5
- // Export types and models from HttpProxy
6
- export * from '../proxies/http-proxy/models/http-types.js';
5
+ // Export types and models
6
+ export * from './models/http-types.js';
7
7
 
8
8
  // Export router functionality
9
9
  export * from './router/index.js';
@@ -1,6 +1,149 @@
1
1
  /**
2
- * This file re-exports HTTP types from the HttpProxy module
3
- * for backward compatibility. All HTTP types are now consolidated
4
- * in the HttpProxy module.
2
+ * HTTP types for routing module.
3
+ * These were previously in http-proxy and are now self-contained here.
5
4
  */
6
- export * from '../../proxies/http-proxy/models/http-types.js';
5
+ import * as plugins from '../../plugins.js';
6
+ import { HttpStatus as ProtocolHttpStatus, getStatusText as getProtocolStatusText } from '../../protocols/http/index.js';
7
+
8
+ /**
9
+ * HTTP-specific event types
10
+ */
11
+ export enum HttpEvents {
12
+ REQUEST_RECEIVED = 'request-received',
13
+ REQUEST_FORWARDED = 'request-forwarded',
14
+ REQUEST_HANDLED = 'request-handled',
15
+ REQUEST_ERROR = 'request-error',
16
+ }
17
+
18
+ // Re-export for backward compatibility with subset of commonly used codes
19
+ export const HttpStatus = {
20
+ OK: ProtocolHttpStatus.OK,
21
+ MOVED_PERMANENTLY: ProtocolHttpStatus.MOVED_PERMANENTLY,
22
+ FOUND: ProtocolHttpStatus.FOUND,
23
+ TEMPORARY_REDIRECT: ProtocolHttpStatus.TEMPORARY_REDIRECT,
24
+ PERMANENT_REDIRECT: ProtocolHttpStatus.PERMANENT_REDIRECT,
25
+ BAD_REQUEST: ProtocolHttpStatus.BAD_REQUEST,
26
+ UNAUTHORIZED: ProtocolHttpStatus.UNAUTHORIZED,
27
+ FORBIDDEN: ProtocolHttpStatus.FORBIDDEN,
28
+ NOT_FOUND: ProtocolHttpStatus.NOT_FOUND,
29
+ METHOD_NOT_ALLOWED: ProtocolHttpStatus.METHOD_NOT_ALLOWED,
30
+ REQUEST_TIMEOUT: ProtocolHttpStatus.REQUEST_TIMEOUT,
31
+ TOO_MANY_REQUESTS: ProtocolHttpStatus.TOO_MANY_REQUESTS,
32
+ INTERNAL_SERVER_ERROR: ProtocolHttpStatus.INTERNAL_SERVER_ERROR,
33
+ NOT_IMPLEMENTED: ProtocolHttpStatus.NOT_IMPLEMENTED,
34
+ BAD_GATEWAY: ProtocolHttpStatus.BAD_GATEWAY,
35
+ SERVICE_UNAVAILABLE: ProtocolHttpStatus.SERVICE_UNAVAILABLE,
36
+ GATEWAY_TIMEOUT: ProtocolHttpStatus.GATEWAY_TIMEOUT,
37
+ } as const;
38
+
39
+ /**
40
+ * Base error class for HTTP-related errors
41
+ */
42
+ export class HttpError extends Error {
43
+ constructor(message: string, public readonly statusCode: number = HttpStatus.INTERNAL_SERVER_ERROR) {
44
+ super(message);
45
+ this.name = 'HttpError';
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Error related to certificate operations
51
+ */
52
+ export class CertificateError extends HttpError {
53
+ constructor(
54
+ message: string,
55
+ public readonly domain: string,
56
+ public readonly isRenewal: boolean = false
57
+ ) {
58
+ super(`${message} for domain ${domain}${isRenewal ? ' (renewal)' : ''}`, HttpStatus.INTERNAL_SERVER_ERROR);
59
+ this.name = 'CertificateError';
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Error related to server operations
65
+ */
66
+ export class ServerError extends HttpError {
67
+ constructor(message: string, public readonly code?: string, statusCode: number = HttpStatus.INTERNAL_SERVER_ERROR) {
68
+ super(message, statusCode);
69
+ this.name = 'ServerError';
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Error for bad requests
75
+ */
76
+ export class BadRequestError extends HttpError {
77
+ constructor(message: string) {
78
+ super(message, HttpStatus.BAD_REQUEST);
79
+ this.name = 'BadRequestError';
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Error for not found resources
85
+ */
86
+ export class NotFoundError extends HttpError {
87
+ constructor(message: string = 'Resource not found') {
88
+ super(message, HttpStatus.NOT_FOUND);
89
+ this.name = 'NotFoundError';
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Redirect configuration for HTTP requests
95
+ */
96
+ export interface IRedirectConfig {
97
+ source: string;
98
+ destination: string;
99
+ type: number;
100
+ preserveQuery?: boolean;
101
+ }
102
+
103
+ /**
104
+ * HTTP router configuration
105
+ */
106
+ export interface IRouterConfig {
107
+ routes: Array<{
108
+ path: string;
109
+ method?: string;
110
+ handler: (req: plugins.http.IncomingMessage, res: plugins.http.ServerResponse) => void | Promise<void>;
111
+ }>;
112
+ notFoundHandler?: (req: plugins.http.IncomingMessage, res: plugins.http.ServerResponse) => void;
113
+ errorHandler?: (error: Error, req: plugins.http.IncomingMessage, res: plugins.http.ServerResponse) => void;
114
+ }
115
+
116
+ /**
117
+ * HTTP request method types
118
+ */
119
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS' | 'CONNECT' | 'TRACE';
120
+
121
+ /**
122
+ * Helper function to get HTTP status text
123
+ */
124
+ export function getStatusText(status: number): string {
125
+ return getProtocolStatusText(status as ProtocolHttpStatus);
126
+ }
127
+
128
+ // Legacy interfaces for backward compatibility
129
+ export interface IDomainOptions {
130
+ domainName: string;
131
+ sslRedirect: boolean;
132
+ acmeMaintenance: boolean;
133
+ forward?: { ip: string; port: number };
134
+ acmeForward?: { ip: string; port: number };
135
+ }
136
+
137
+ export interface IDomainCertificate {
138
+ options: IDomainOptions;
139
+ certObtained: boolean;
140
+ obtainingInProgress: boolean;
141
+ certificate?: string;
142
+ privateKey?: string;
143
+ expiryDate?: Date;
144
+ lastRenewalAttempt?: Date;
145
+ }
146
+
147
+ // Backward compatibility exports
148
+ export { HttpError as Port80HandlerError };
149
+ export { CertificateError as CertError };