before refactor
This commit is contained in:
		| @@ -12,6 +12,10 @@ import { Port80Handler } from '../port80handler/classes.port80handler.js'; | ||||
|  * automatic certificate management, and high-performance connection pooling. | ||||
|  */ | ||||
| export class NetworkProxy implements IMetricsTracker { | ||||
|   // Provide a minimal JSON representation to avoid circular references during deep equality checks | ||||
|   public toJSON(): any { | ||||
|     return {}; | ||||
|   } | ||||
|   // Configuration | ||||
|   public options: INetworkProxyOptions; | ||||
|   public proxyConfigs: IReverseProxyConfig[] = []; | ||||
|   | ||||
| @@ -22,13 +22,15 @@ import * as smartpromise from '@push.rocks/smartpromise'; | ||||
| import * as smartrequest from '@push.rocks/smartrequest'; | ||||
| import * as smartstring from '@push.rocks/smartstring'; | ||||
|  | ||||
| export { lik, smartdelay, smartrequest, smartpromise, smartstring }; | ||||
| import * as smartacme from '@push.rocks/smartacme'; | ||||
| import * as smartacmePlugins from '@push.rocks/smartacme/dist_ts/smartacme.plugins.js'; | ||||
| import * as smartacmeHandlers from '@push.rocks/smartacme/dist_ts/handlers/index.js'; | ||||
| export { lik, smartdelay, smartrequest, smartpromise, smartstring, smartacme, smartacmePlugins, smartacmeHandlers }; | ||||
|  | ||||
| // third party scope | ||||
| import * as acme from 'acme-client'; | ||||
| import prettyMs from 'pretty-ms'; | ||||
| import * as ws from 'ws'; | ||||
| import wsDefault from 'ws'; | ||||
| import { minimatch } from 'minimatch'; | ||||
|  | ||||
| export { acme, prettyMs, ws, wsDefault, minimatch }; | ||||
| export { prettyMs, ws, wsDefault, minimatch }; | ||||
|   | ||||
| @@ -2,6 +2,21 @@ import * as plugins from '../plugins.js'; | ||||
| import { IncomingMessage, ServerResponse } from 'http'; | ||||
| import * as fs from 'fs'; | ||||
| import * as path from 'path'; | ||||
| // ACME HTTP-01 challenge handler storing tokens in memory (diskless) | ||||
| class DisklessHttp01Handler { | ||||
|   private storage: Map<string, string>; | ||||
|   constructor(storage: Map<string, string>) { this.storage = storage; } | ||||
|   public getSupportedTypes(): string[] { return ['http-01']; } | ||||
|   public async prepare(ch: any): Promise<void> { | ||||
|     this.storage.set(ch.token, ch.keyAuthorization); | ||||
|   } | ||||
|   public async verify(ch: any): Promise<void> { | ||||
|     return; | ||||
|   } | ||||
|   public async cleanup(ch: any): Promise<void> { | ||||
|     this.storage.delete(ch.token); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Custom error classes for better error handling | ||||
| @@ -79,6 +94,7 @@ interface IPort80HandlerOptions { | ||||
|   autoRenew?: boolean; // Whether to automatically renew certificates | ||||
|   certificateStore?: string; // Directory to store certificates | ||||
|   skipConfiguredCerts?: boolean; // Skip domains that already have certificates | ||||
|   mongoDescriptor?: plugins.smartdata.IMongoDescriptor; // MongoDB config for SmartAcme | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -128,6 +144,10 @@ export interface ICertificateExpiring { | ||||
|  */ | ||||
| export class Port80Handler extends plugins.EventEmitter { | ||||
|   private domainCertificates: Map<string, IDomainCertificate>; | ||||
|   // In-memory storage for ACME HTTP-01 challenge tokens | ||||
|   private acmeHttp01Storage: Map<string, string> = new Map(); | ||||
|   // SmartAcme instance for certificate management | ||||
|   private smartAcme: plugins.smartacme.SmartAcme | null = null; | ||||
|   private server: plugins.http.Server | null = null; | ||||
|   private acmeClient: plugins.acme.Client | null = null; | ||||
|   private accountKey: string | null = null; | ||||
| @@ -175,6 +195,20 @@ export class Port80Handler extends plugins.EventEmitter { | ||||
|       console.log('Port80Handler is disabled, skipping start'); | ||||
|       return; | ||||
|     } | ||||
|     // Initialize SmartAcme for ACME challenge management (diskless HTTP handler) | ||||
|     if (this.options.enabled) { | ||||
|       if (!this.options.mongoDescriptor) { | ||||
|         throw new ServerError('MongoDB descriptor is required for SmartAcme'); | ||||
|       } | ||||
|       this.smartAcme = new plugins.smartacme.SmartAcme({ | ||||
|         accountEmail: this.options.contactEmail, | ||||
|         environment: this.options.useProduction ? 'production' : 'integration', | ||||
|         mongoDescriptor: this.options.mongoDescriptor, | ||||
|         challengeHandlers: [ new DisklessHttp01Handler(this.acmeHttp01Storage) ], | ||||
|         challengePriority: ['http-01'], | ||||
|       }); | ||||
|       await this.smartAcme.start(); | ||||
|     } | ||||
|  | ||||
|     return new Promise((resolve, reject) => { | ||||
|       try { | ||||
| @@ -640,19 +674,26 @@ export class Port80Handler extends plugins.EventEmitter { | ||||
|     const { domainInfo, pattern } = domainMatch; | ||||
|     const options = domainInfo.options; | ||||
|  | ||||
|     // If the request is for an ACME HTTP-01 challenge, handle it | ||||
|     if (req.url && req.url.startsWith('/.well-known/acme-challenge/') && (options.acmeMaintenance || options.acmeForward)) { | ||||
|       // Check if we should forward ACME requests | ||||
|     // Serve or forward ACME HTTP-01 challenge requests | ||||
|     if (req.url && req.url.startsWith('/.well-known/acme-challenge/') && options.acmeMaintenance) { | ||||
|       // Forward ACME requests if configured | ||||
|       if (options.acmeForward) { | ||||
|         this.forwardRequest(req, res, options.acmeForward, 'ACME challenge'); | ||||
|         return; | ||||
|       } | ||||
|        | ||||
|       // Only handle ACME challenges for non-glob patterns | ||||
|       if (!this.isGlobPattern(pattern)) { | ||||
|         this.handleAcmeChallenge(req, res, domain); | ||||
|         return; | ||||
|       // Serve challenge response from in-memory storage | ||||
|       const token = req.url.split('/').pop() || ''; | ||||
|       const keyAuth = this.acmeHttp01Storage.get(token); | ||||
|       if (keyAuth) { | ||||
|         res.statusCode = 200; | ||||
|         res.setHeader('Content-Type', 'text/plain'); | ||||
|         res.end(keyAuth); | ||||
|         console.log(`Served ACME challenge response for ${domain}`); | ||||
|       } else { | ||||
|         res.statusCode = 404; | ||||
|         res.end('Challenge token not found'); | ||||
|       } | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     // Check if we should forward non-ACME requests | ||||
|   | ||||
		Reference in New Issue
	
	Block a user