@push.rocks/smartproxy 22.4.2 → 23.0.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 (101) hide show
  1. package/changelog.md +36 -0
  2. package/dist_rust/rustproxy +0 -0
  3. package/dist_ts/00_commitinfo_data.js +1 -1
  4. package/dist_ts/index.d.ts +1 -6
  5. package/dist_ts/index.js +3 -11
  6. package/dist_ts/protocols/common/fragment-handler.js +5 -1
  7. package/dist_ts/proxies/index.d.ts +1 -6
  8. package/dist_ts/proxies/index.js +2 -8
  9. package/dist_ts/proxies/smart-proxy/index.d.ts +5 -10
  10. package/dist_ts/proxies/smart-proxy/index.js +7 -13
  11. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +5 -2
  12. package/dist_ts/proxies/smart-proxy/models/route-types.js +1 -1
  13. package/dist_ts/proxies/smart-proxy/route-preprocessor.d.ts +37 -0
  14. package/dist_ts/proxies/smart-proxy/route-preprocessor.js +103 -0
  15. package/dist_ts/proxies/smart-proxy/rust-binary-locator.d.ts +23 -0
  16. package/dist_ts/proxies/smart-proxy/rust-binary-locator.js +104 -0
  17. package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.d.ts +74 -0
  18. package/dist_ts/proxies/smart-proxy/rust-metrics-adapter.js +146 -0
  19. package/dist_ts/proxies/smart-proxy/rust-proxy-bridge.d.ts +49 -0
  20. package/dist_ts/proxies/smart-proxy/rust-proxy-bridge.js +259 -0
  21. package/dist_ts/proxies/smart-proxy/smart-proxy.d.ts +39 -157
  22. package/dist_ts/proxies/smart-proxy/smart-proxy.js +224 -621
  23. package/dist_ts/proxies/smart-proxy/socket-handler-server.d.ts +45 -0
  24. package/dist_ts/proxies/smart-proxy/socket-handler-server.js +253 -0
  25. package/dist_ts/routing/index.d.ts +1 -1
  26. package/dist_ts/routing/index.js +3 -3
  27. package/dist_ts/routing/models/http-types.d.ts +119 -4
  28. package/dist_ts/routing/models/http-types.js +93 -5
  29. package/package.json +1 -1
  30. package/readme.md +444 -219
  31. package/ts/00_commitinfo_data.ts +1 -1
  32. package/ts/index.ts +4 -15
  33. package/ts/protocols/common/fragment-handler.ts +4 -0
  34. package/ts/proxies/index.ts +1 -12
  35. package/ts/proxies/smart-proxy/index.ts +6 -13
  36. package/ts/proxies/smart-proxy/models/interfaces.ts +6 -4
  37. package/ts/proxies/smart-proxy/models/route-types.ts +0 -2
  38. package/ts/proxies/smart-proxy/route-preprocessor.ts +122 -0
  39. package/ts/proxies/smart-proxy/rust-binary-locator.ts +112 -0
  40. package/ts/proxies/smart-proxy/rust-metrics-adapter.ts +161 -0
  41. package/ts/proxies/smart-proxy/rust-proxy-bridge.ts +310 -0
  42. package/ts/proxies/smart-proxy/smart-proxy.ts +282 -798
  43. package/ts/proxies/smart-proxy/socket-handler-server.ts +279 -0
  44. package/ts/routing/index.ts +2 -2
  45. package/ts/routing/models/http-types.ts +147 -4
  46. package/dist_ts/proxies/nftables-proxy/index.d.ts +0 -6
  47. package/dist_ts/proxies/nftables-proxy/index.js +0 -7
  48. package/dist_ts/proxies/nftables-proxy/models/errors.d.ts +0 -15
  49. package/dist_ts/proxies/nftables-proxy/models/errors.js +0 -28
  50. package/dist_ts/proxies/nftables-proxy/models/index.d.ts +0 -5
  51. package/dist_ts/proxies/nftables-proxy/models/index.js +0 -6
  52. package/dist_ts/proxies/nftables-proxy/models/interfaces.d.ts +0 -75
  53. package/dist_ts/proxies/nftables-proxy/models/interfaces.js +0 -5
  54. package/dist_ts/proxies/nftables-proxy/nftables-proxy.d.ts +0 -124
  55. package/dist_ts/proxies/nftables-proxy/nftables-proxy.js +0 -1374
  56. package/dist_ts/proxies/nftables-proxy/utils/index.d.ts +0 -9
  57. package/dist_ts/proxies/nftables-proxy/utils/index.js +0 -12
  58. package/dist_ts/proxies/nftables-proxy/utils/nft-command-executor.d.ts +0 -66
  59. package/dist_ts/proxies/nftables-proxy/utils/nft-command-executor.js +0 -131
  60. package/dist_ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.d.ts +0 -39
  61. package/dist_ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.js +0 -112
  62. package/dist_ts/proxies/nftables-proxy/utils/nft-rule-validator.d.ts +0 -59
  63. package/dist_ts/proxies/nftables-proxy/utils/nft-rule-validator.js +0 -130
  64. package/ts/proxies/http-proxy/connection-pool.ts +0 -228
  65. package/ts/proxies/http-proxy/context-creator.ts +0 -145
  66. package/ts/proxies/http-proxy/default-certificates.ts +0 -150
  67. package/ts/proxies/http-proxy/function-cache.ts +0 -279
  68. package/ts/proxies/http-proxy/handlers/index.ts +0 -5
  69. package/ts/proxies/http-proxy/http-proxy.ts +0 -669
  70. package/ts/proxies/http-proxy/http-request-handler.ts +0 -331
  71. package/ts/proxies/http-proxy/http2-request-handler.ts +0 -255
  72. package/ts/proxies/http-proxy/index.ts +0 -18
  73. package/ts/proxies/http-proxy/models/http-types.ts +0 -148
  74. package/ts/proxies/http-proxy/models/index.ts +0 -5
  75. package/ts/proxies/http-proxy/models/types.ts +0 -125
  76. package/ts/proxies/http-proxy/request-handler.ts +0 -878
  77. package/ts/proxies/http-proxy/security-manager.ts +0 -413
  78. package/ts/proxies/http-proxy/websocket-handler.ts +0 -581
  79. package/ts/proxies/nftables-proxy/index.ts +0 -6
  80. package/ts/proxies/nftables-proxy/models/errors.ts +0 -30
  81. package/ts/proxies/nftables-proxy/models/index.ts +0 -5
  82. package/ts/proxies/nftables-proxy/models/interfaces.ts +0 -94
  83. package/ts/proxies/nftables-proxy/nftables-proxy.ts +0 -1754
  84. package/ts/proxies/nftables-proxy/utils/index.ts +0 -38
  85. package/ts/proxies/nftables-proxy/utils/nft-command-executor.ts +0 -162
  86. package/ts/proxies/nftables-proxy/utils/nft-port-spec-normalizer.ts +0 -125
  87. package/ts/proxies/nftables-proxy/utils/nft-rule-validator.ts +0 -156
  88. package/ts/proxies/smart-proxy/acme-state-manager.ts +0 -112
  89. package/ts/proxies/smart-proxy/cert-store.ts +0 -92
  90. package/ts/proxies/smart-proxy/certificate-manager.ts +0 -895
  91. package/ts/proxies/smart-proxy/connection-manager.ts +0 -809
  92. package/ts/proxies/smart-proxy/http-proxy-bridge.ts +0 -213
  93. package/ts/proxies/smart-proxy/metrics-collector.ts +0 -453
  94. package/ts/proxies/smart-proxy/nftables-manager.ts +0 -271
  95. package/ts/proxies/smart-proxy/port-manager.ts +0 -358
  96. package/ts/proxies/smart-proxy/route-connection-handler.ts +0 -1712
  97. package/ts/proxies/smart-proxy/route-orchestrator.ts +0 -297
  98. package/ts/proxies/smart-proxy/security-manager.ts +0 -269
  99. package/ts/proxies/smart-proxy/throughput-tracker.ts +0 -138
  100. package/ts/proxies/smart-proxy/timeout-manager.ts +0 -196
  101. package/ts/proxies/smart-proxy/tls-manager.ts +0 -171
@@ -1,228 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import { type IHttpProxyOptions, type IConnectionEntry, type ILogger, createLogger } from './models/types.js';
3
- import { cleanupSocket } from '../../core/utils/socket-utils.js';
4
-
5
- /**
6
- * Manages a pool of backend connections for efficient reuse
7
- */
8
- export class ConnectionPool {
9
- private connectionPool: Map<string, Array<IConnectionEntry>> = new Map();
10
- private roundRobinPositions: Map<string, number> = new Map();
11
- private logger: ILogger;
12
-
13
- constructor(private options: IHttpProxyOptions) {
14
- this.logger = createLogger(options.logLevel || 'info');
15
- }
16
-
17
- /**
18
- * Get a connection from the pool or create a new one
19
- */
20
- public getConnection(host: string, port: number): Promise<plugins.net.Socket> {
21
- return new Promise((resolve, reject) => {
22
- const poolKey = `${host}:${port}`;
23
- const connectionList = this.connectionPool.get(poolKey) || [];
24
-
25
- // Look for an idle connection
26
- const idleConnectionIndex = connectionList.findIndex(c => c.isIdle);
27
-
28
- if (idleConnectionIndex >= 0) {
29
- // Get existing connection from pool
30
- const connection = connectionList[idleConnectionIndex];
31
- connection.isIdle = false;
32
- connection.lastUsed = Date.now();
33
- this.logger.debug(`Reusing connection from pool for ${poolKey}`);
34
-
35
- // Update the pool
36
- this.connectionPool.set(poolKey, connectionList);
37
-
38
- resolve(connection.socket);
39
- return;
40
- }
41
-
42
- // No idle connection available, create a new one if pool isn't full
43
- const poolSize = this.options.connectionPoolSize || 50;
44
- if (connectionList.length < poolSize) {
45
- this.logger.debug(`Creating new connection to ${host}:${port}`);
46
-
47
- try {
48
- const socket = plugins.net.connect({
49
- host,
50
- port,
51
- keepAlive: true,
52
- keepAliveInitialDelay: 30000 // 30 seconds
53
- });
54
-
55
- socket.once('connect', () => {
56
- // Add to connection pool
57
- const connection = {
58
- socket,
59
- lastUsed: Date.now(),
60
- isIdle: false
61
- };
62
-
63
- connectionList.push(connection);
64
- this.connectionPool.set(poolKey, connectionList);
65
-
66
- // Setup cleanup when the connection is closed
67
- socket.once('close', () => {
68
- const idx = connectionList.findIndex(c => c.socket === socket);
69
- if (idx >= 0) {
70
- connectionList.splice(idx, 1);
71
- this.connectionPool.set(poolKey, connectionList);
72
- this.logger.debug(`Removed closed connection from pool for ${poolKey}`);
73
- }
74
- });
75
-
76
- resolve(socket);
77
- });
78
-
79
- socket.once('error', (err) => {
80
- this.logger.error(`Error creating connection to ${host}:${port}`, err);
81
- reject(err);
82
- });
83
- } catch (err) {
84
- this.logger.error(`Failed to create connection to ${host}:${port}`, err);
85
- reject(err);
86
- }
87
- } else {
88
- // Pool is full, wait for an idle connection or reject
89
- this.logger.warn(`Connection pool for ${poolKey} is full (${connectionList.length})`);
90
- reject(new Error(`Connection pool for ${poolKey} is full`));
91
- }
92
- });
93
- }
94
-
95
- /**
96
- * Return a connection to the pool for reuse
97
- */
98
- public returnConnection(socket: plugins.net.Socket, host: string, port: number): void {
99
- const poolKey = `${host}:${port}`;
100
- const connectionList = this.connectionPool.get(poolKey) || [];
101
-
102
- // Find this connection in the pool
103
- const connectionIndex = connectionList.findIndex(c => c.socket === socket);
104
-
105
- if (connectionIndex >= 0) {
106
- // Mark as idle and update last used time
107
- connectionList[connectionIndex].isIdle = true;
108
- connectionList[connectionIndex].lastUsed = Date.now();
109
-
110
- this.logger.debug(`Returned connection to pool for ${poolKey}`);
111
- } else {
112
- this.logger.warn(`Attempted to return unknown connection to pool for ${poolKey}`);
113
- }
114
- }
115
-
116
- /**
117
- * Cleanup the connection pool by removing idle connections
118
- * or reducing pool size if it exceeds the configured maximum
119
- */
120
- public cleanupConnectionPool(): void {
121
- const now = Date.now();
122
- const idleTimeout = this.options.keepAliveTimeout || 120000; // 2 minutes default
123
-
124
- for (const [host, connections] of this.connectionPool.entries()) {
125
- // Sort by last used time (oldest first)
126
- connections.sort((a, b) => a.lastUsed - b.lastUsed);
127
-
128
- // Remove idle connections older than the idle timeout
129
- let removed = 0;
130
- while (connections.length > 0) {
131
- const connection = connections[0];
132
-
133
- // Remove if idle and exceeds timeout, or if pool is too large
134
- if ((connection.isIdle && now - connection.lastUsed > idleTimeout) ||
135
- connections.length > (this.options.connectionPoolSize || 50)) {
136
-
137
- cleanupSocket(connection.socket, `pool-${host}-idle`, { immediate: true }).catch(() => {});
138
-
139
- connections.shift(); // Remove from pool
140
- removed++;
141
- } else {
142
- break; // Stop removing if we've reached active or recent connections
143
- }
144
- }
145
-
146
- if (removed > 0) {
147
- this.logger.debug(`Removed ${removed} idle connections from pool for ${host}, ${connections.length} remaining`);
148
- }
149
-
150
- // Update the pool with the remaining connections
151
- if (connections.length === 0) {
152
- this.connectionPool.delete(host);
153
- } else {
154
- this.connectionPool.set(host, connections);
155
- }
156
- }
157
- }
158
-
159
- /**
160
- * Close all connections in the pool
161
- */
162
- public closeAllConnections(): void {
163
- for (const [host, connections] of this.connectionPool.entries()) {
164
- this.logger.debug(`Closing ${connections.length} connections to ${host}`);
165
-
166
- for (const connection of connections) {
167
- cleanupSocket(connection.socket, `pool-${host}-close`, { immediate: true }).catch(() => {});
168
- }
169
- }
170
-
171
- this.connectionPool.clear();
172
- this.roundRobinPositions.clear();
173
- }
174
-
175
- /**
176
- * Get load balancing target using round-robin
177
- */
178
- public getNextTarget(targets: string[], port: number): { host: string, port: number } {
179
- const targetKey = targets.join(',');
180
-
181
- // Initialize position if not exists
182
- if (!this.roundRobinPositions.has(targetKey)) {
183
- this.roundRobinPositions.set(targetKey, 0);
184
- }
185
-
186
- // Get current position and increment for next time
187
- const currentPosition = this.roundRobinPositions.get(targetKey)!;
188
- const nextPosition = (currentPosition + 1) % targets.length;
189
- this.roundRobinPositions.set(targetKey, nextPosition);
190
-
191
- // Return the selected target
192
- return {
193
- host: targets[currentPosition],
194
- port
195
- };
196
- }
197
-
198
- /**
199
- * Gets the connection pool status
200
- */
201
- public getPoolStatus(): Record<string, { total: number, idle: number }> {
202
- return Object.fromEntries(
203
- Array.from(this.connectionPool.entries()).map(([host, connections]) => [
204
- host,
205
- {
206
- total: connections.length,
207
- idle: connections.filter(c => c.isIdle).length
208
- }
209
- ])
210
- );
211
- }
212
-
213
- /**
214
- * Setup a periodic cleanup task
215
- */
216
- public setupPeriodicCleanup(interval: number = 60000): NodeJS.Timeout {
217
- const timer = setInterval(() => {
218
- this.cleanupConnectionPool();
219
- }, interval);
220
-
221
- // Don't prevent process exit
222
- if (timer.unref) {
223
- timer.unref();
224
- }
225
-
226
- return timer;
227
- }
228
- }
@@ -1,145 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import '../../core/models/socket-augmentation.js';
3
- import type { IRouteContext, IHttpRouteContext, IHttp2RouteContext } from '../../core/models/route-context.js';
4
-
5
- /**
6
- * Context creator for NetworkProxy
7
- * Creates route contexts for matching and function evaluation
8
- */
9
- export class ContextCreator {
10
- /**
11
- * Create a route context from HTTP request information
12
- */
13
- public createHttpRouteContext(req: any, options: {
14
- tlsVersion?: string;
15
- connectionId: string;
16
- clientIp: string;
17
- serverIp: string;
18
- }): IHttpRouteContext {
19
- // Parse headers
20
- const headers: Record<string, string> = {};
21
- for (const [key, value] of Object.entries(req.headers)) {
22
- if (typeof value === 'string') {
23
- headers[key.toLowerCase()] = value;
24
- } else if (Array.isArray(value) && value.length > 0) {
25
- headers[key.toLowerCase()] = value[0];
26
- }
27
- }
28
-
29
- // Parse domain from Host header
30
- const domain = headers['host']?.split(':')[0] || '';
31
-
32
- // Parse URL
33
- const url = new URL(`http://${domain}${req.url || '/'}`);
34
-
35
- return {
36
- // Connection basics
37
- port: req.socket.localPort || 0,
38
- domain,
39
- clientIp: options.clientIp,
40
- serverIp: options.serverIp,
41
-
42
- // HTTP specifics
43
- path: url.pathname,
44
- query: url.search ? url.search.substring(1) : '',
45
- headers,
46
-
47
- // TLS information
48
- isTls: !!req.socket.encrypted,
49
- tlsVersion: options.tlsVersion,
50
-
51
- // Request objects
52
- req,
53
-
54
- // Metadata
55
- timestamp: Date.now(),
56
- connectionId: options.connectionId
57
- };
58
- }
59
-
60
- /**
61
- * Create a route context from HTTP/2 stream and headers
62
- */
63
- public createHttp2RouteContext(
64
- stream: plugins.http2.ServerHttp2Stream,
65
- headers: plugins.http2.IncomingHttpHeaders,
66
- options: {
67
- connectionId: string;
68
- clientIp: string;
69
- serverIp: string;
70
- }
71
- ): IHttp2RouteContext {
72
- // Parse headers, excluding HTTP/2 pseudo-headers
73
- const processedHeaders: Record<string, string> = {};
74
- for (const [key, value] of Object.entries(headers)) {
75
- if (!key.startsWith(':') && typeof value === 'string') {
76
- processedHeaders[key.toLowerCase()] = value;
77
- }
78
- }
79
-
80
- // Get domain from :authority pseudo-header
81
- const authority = headers[':authority'] as string || '';
82
- const domain = authority.split(':')[0];
83
-
84
- // Get path from :path pseudo-header
85
- const path = headers[':path'] as string || '/';
86
-
87
- // Parse the path to extract query string
88
- const pathParts = path.split('?');
89
- const pathname = pathParts[0];
90
- const query = pathParts.length > 1 ? pathParts[1] : '';
91
-
92
- // Get the socket from the session
93
- const socket = (stream.session as any)?.socket;
94
-
95
- return {
96
- // Connection basics
97
- port: socket?.localPort || 0,
98
- domain,
99
- clientIp: options.clientIp,
100
- serverIp: options.serverIp,
101
-
102
- // HTTP specifics
103
- path: pathname,
104
- query,
105
- headers: processedHeaders,
106
-
107
- // HTTP/2 specific properties
108
- method: headers[':method'] as string,
109
- stream,
110
-
111
- // TLS information - HTTP/2 is always on TLS in browsers
112
- isTls: true,
113
- tlsVersion: socket?.getTLSVersion?.() || 'TLSv1.3',
114
-
115
- // Metadata
116
- timestamp: Date.now(),
117
- connectionId: options.connectionId
118
- };
119
- }
120
-
121
- /**
122
- * Create a basic route context from socket information
123
- */
124
- public createSocketRouteContext(socket: plugins.net.Socket, options: {
125
- domain?: string;
126
- tlsVersion?: string;
127
- connectionId: string;
128
- }): IRouteContext {
129
- return {
130
- // Connection basics
131
- port: socket.localPort || 0,
132
- domain: options.domain,
133
- clientIp: socket.remoteAddress?.replace('::ffff:', '') || '0.0.0.0',
134
- serverIp: socket.localAddress?.replace('::ffff:', '') || '0.0.0.0',
135
-
136
- // TLS information
137
- isTls: options.tlsVersion !== undefined,
138
- tlsVersion: options.tlsVersion,
139
-
140
- // Metadata
141
- timestamp: Date.now(),
142
- connectionId: options.connectionId
143
- };
144
- }
145
- }
@@ -1,150 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import * as fs from 'fs';
3
- import * as path from 'path';
4
- import { fileURLToPath } from 'url';
5
- import { AsyncFileSystem } from '../../core/utils/fs-utils.js';
6
- import type { ILogger, ICertificateEntry } from './models/types.js';
7
-
8
- /**
9
- * Interface for default certificate data
10
- */
11
- export interface IDefaultCertificates {
12
- key: string;
13
- cert: string;
14
- }
15
-
16
- /**
17
- * Provides default SSL certificates for HttpProxy.
18
- * This is a minimal replacement for the deprecated CertificateManager.
19
- *
20
- * For production certificate management, use SmartCertManager instead.
21
- */
22
- export class DefaultCertificateProvider {
23
- private defaultCertificates: IDefaultCertificates | null = null;
24
- private certificateCache: Map<string, ICertificateEntry> = new Map();
25
- private initialized = false;
26
-
27
- constructor(private logger?: ILogger) {}
28
-
29
- /**
30
- * Load default certificates asynchronously (preferred)
31
- */
32
- public async loadDefaultCertificatesAsync(): Promise<IDefaultCertificates> {
33
- if (this.defaultCertificates) {
34
- return this.defaultCertificates;
35
- }
36
-
37
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
38
- const certPath = path.join(__dirname, '..', '..', '..', 'assets', 'certs');
39
-
40
- try {
41
- const [key, cert] = await Promise.all([
42
- AsyncFileSystem.readFile(path.join(certPath, 'key.pem')),
43
- AsyncFileSystem.readFile(path.join(certPath, 'cert.pem'))
44
- ]);
45
-
46
- this.defaultCertificates = { key, cert };
47
- this.logger?.info?.('Loaded default certificates from filesystem');
48
- this.initialized = true;
49
- return this.defaultCertificates;
50
- } catch (error) {
51
- this.logger?.warn?.(`Failed to load default certificates: ${error}`);
52
- this.defaultCertificates = this.generateFallbackCertificate();
53
- this.initialized = true;
54
- return this.defaultCertificates;
55
- }
56
- }
57
-
58
- /**
59
- * Load default certificates synchronously (for backward compatibility)
60
- * @deprecated Use loadDefaultCertificatesAsync instead
61
- */
62
- public loadDefaultCertificatesSync(): IDefaultCertificates {
63
- if (this.defaultCertificates) {
64
- return this.defaultCertificates;
65
- }
66
-
67
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
68
- const certPath = path.join(__dirname, '..', '..', '..', 'assets', 'certs');
69
-
70
- try {
71
- this.defaultCertificates = {
72
- key: fs.readFileSync(path.join(certPath, 'key.pem'), 'utf8'),
73
- cert: fs.readFileSync(path.join(certPath, 'cert.pem'), 'utf8')
74
- };
75
- this.logger?.info?.('Loaded default certificates from filesystem (sync)');
76
- } catch (error) {
77
- this.logger?.warn?.(`Failed to load default certificates: ${error}`);
78
- this.defaultCertificates = this.generateFallbackCertificate();
79
- }
80
-
81
- this.initialized = true;
82
- return this.defaultCertificates;
83
- }
84
-
85
- /**
86
- * Gets the default certificates (loads synchronously if not already loaded)
87
- */
88
- public getDefaultCertificates(): IDefaultCertificates {
89
- if (!this.defaultCertificates) {
90
- return this.loadDefaultCertificatesSync();
91
- }
92
- return this.defaultCertificates;
93
- }
94
-
95
- /**
96
- * Updates a certificate in the cache
97
- */
98
- public updateCertificate(domain: string, cert: string, key: string): void {
99
- this.certificateCache.set(domain, {
100
- cert,
101
- key,
102
- expires: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000) // 90 days
103
- });
104
-
105
- this.logger?.info?.(`Certificate updated for ${domain}`);
106
- }
107
-
108
- /**
109
- * Gets a cached certificate
110
- */
111
- public getCachedCertificate(domain: string): ICertificateEntry | null {
112
- return this.certificateCache.get(domain) || null;
113
- }
114
-
115
- /**
116
- * Gets statistics for metrics
117
- */
118
- public getStats(): { cachedCertificates: number; defaultCertEnabled: boolean } {
119
- return {
120
- cachedCertificates: this.certificateCache.size,
121
- defaultCertEnabled: this.defaultCertificates !== null
122
- };
123
- }
124
-
125
- /**
126
- * Generate a fallback self-signed certificate placeholder
127
- * Note: This is just a placeholder - real apps should provide proper certificates
128
- */
129
- private generateFallbackCertificate(): IDefaultCertificates {
130
- this.logger?.warn?.('Using fallback self-signed certificate placeholder');
131
-
132
- // Minimal self-signed certificate for fallback only
133
- // In production, proper certificates should be provided via SmartCertManager
134
- const selfSignedCert = `-----BEGIN CERTIFICATE-----
135
- MIIBkTCB+wIJAKHHIgIIA0/cMA0GCSqGSIb3DQEBBQUAMA0xCzAJBgNVBAYTAlVT
136
- MB4XDTE0MDEwMTAwMDAwMFoXDTI0MDEwMTAwMDAwMFowDTELMAkGA1UEBhMCVVMw
137
- gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMRiH0VwnOH3jCV7c6JFZWYrvuqy
138
- -----END CERTIFICATE-----`;
139
-
140
- const selfSignedKey = `-----BEGIN PRIVATE KEY-----
141
- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMRiH0VwnOH3jCV7
142
- c6JFZWYrvuqyALCLXj0pcr1iqNdHjegNXnkl5zjdaUjq4edNOKl7M1AlFiYjG2xk
143
- -----END PRIVATE KEY-----`;
144
-
145
- return {
146
- key: selfSignedKey,
147
- cert: selfSignedCert
148
- };
149
- }
150
- }