@@ -3,6 +3,7 @@ import { Buffer } from 'node:buffer';
33import type dns from 'node:dns' ;
44import { EventEmitter } from 'node:events' ;
55import http from 'node:http' ;
6+ import https from 'node:https' ;
67import type net from 'node:net' ;
78import { URL } from 'node:url' ;
89import util from 'node:util' ;
@@ -91,6 +92,25 @@ export type PrepareRequestFunctionResult = {
9192type Promisable < T > = T | Promise < T > ;
9293export type PrepareRequestFunction = ( opts : PrepareRequestFunctionOpts ) => Promisable < undefined | PrepareRequestFunctionResult > ;
9394
95+ interface ServerOptionsBase {
96+ port ?: number ;
97+ host ?: string ;
98+ prepareRequestFunction ?: PrepareRequestFunction ;
99+ verbose ?: boolean ;
100+ authRealm ?: unknown ;
101+ }
102+
103+ interface HttpServerOptions extends ServerOptionsBase {
104+ serverType ?: 'http' ;
105+ }
106+
107+ interface HttpsServerOptions extends ServerOptionsBase {
108+ serverType : 'https' ;
109+ httpsOptions : https . ServerOptions ;
110+ }
111+
112+ export type ServerOptions = HttpServerOptions | HttpsServerOptions ;
113+
94114/**
95115 * Represents the proxy server.
96116 * It emits the 'requestFailed' event on unexpected request errors, with the following parameter `{ error, request }`.
@@ -107,7 +127,9 @@ export class Server extends EventEmitter {
107127
108128 verbose : boolean ;
109129
110- server : http . Server ;
130+ server : http . Server | https . Server ;
131+
132+ serverType : 'http' | 'https' ;
111133
112134 lastHandlerId : number ;
113135
@@ -119,6 +141,9 @@ export class Server extends EventEmitter {
119141 * Initializes a new instance of Server class.
120142 * @param options
121143 * @param [options.port] Port where the server will listen. By default 8000.
144+ * @param [options.serverType] Type of server to create: 'http' or 'https'. By default 'http'.
145+ * @param [options.httpsOptions] HTTPS server options (required when serverType is 'https').
146+ * Accepts standard Node.js https.ServerOptions including key, cert, ca, passphrase, etc.
122147 * @param [options.prepareRequestFunction] Custom function to authenticate proxy requests,
123148 * provide URL to upstream proxy or potentially provide a function that generates a custom response to HTTP requests.
124149 * It accepts a single parameter which is an object:
@@ -149,13 +174,7 @@ export class Server extends EventEmitter {
149174 * @param [options.authRealm] Realm used in the Proxy-Authenticate header and also in the 'Server' HTTP header. By default it's `ProxyChain`.
150175 * @param [options.verbose] If true, the server will output logs
151176 */
152- constructor ( options : {
153- port ?: number ,
154- host ?: string ,
155- prepareRequestFunction ?: PrepareRequestFunction ,
156- verbose ?: boolean ,
157- authRealm ?: unknown ,
158- } = { } ) {
177+ constructor ( options : ServerOptions = { } ) {
159178 super ( ) ;
160179
161180 if ( options . port === undefined || options . port === null ) {
@@ -169,12 +188,30 @@ export class Server extends EventEmitter {
169188 this . authRealm = options . authRealm || DEFAULT_AUTH_REALM ;
170189 this . verbose = ! ! options . verbose ;
171190
172- this . server = http . createServer ( ) ;
191+ // Create server based on type
192+ if ( options . serverType === 'https' ) {
193+ if ( ! options . httpsOptions ) {
194+ throw new Error ( 'httpsOptions is required when serverType is "https"' ) ;
195+ }
196+ this . server = https . createServer ( options . httpsOptions ) ;
197+ this . serverType = 'https' ;
198+ } else {
199+ this . server = http . createServer ( ) ;
200+ this . serverType = 'http' ;
201+ }
202+
203+ // Attach event handlers (same for both HTTP and HTTPS)
173204 this . server . on ( 'clientError' , this . onClientError . bind ( this ) ) ;
174205 this . server . on ( 'request' , this . onRequest . bind ( this ) ) ;
175206 this . server . on ( 'connect' , this . onConnect . bind ( this ) ) ;
176207 this . server . on ( 'connection' , this . onConnection . bind ( this ) ) ;
177208
209+ // For HTTPS servers, also listen to secureConnection for proper TLS socket handling
210+ // This ensures connection tracking works correctly with TLS sockets
211+ if ( this . serverType === 'https' ) {
212+ this . server . on ( 'secureConnection' , this . onConnection . bind ( this ) ) ;
213+ }
214+
178215 this . lastHandlerId = 0 ;
179216 this . stats = {
180217 httpRequestCount : 0 ,
@@ -615,9 +652,11 @@ export class Server extends EventEmitter {
615652
616653 const targetStats = getTargetStats ( socket ) ;
617654
655+ // For TLS sockets, bytesRead/bytesWritten might not be immediately available
656+ // Use nullish coalescing to ensure we always have valid numeric values
618657 const result = {
619- srcTxBytes : socket . bytesWritten ,
620- srcRxBytes : socket . bytesRead ,
658+ srcTxBytes : socket . bytesWritten ?? 0 ,
659+ srcRxBytes : socket . bytesRead ?? 0 ,
621660 trgTxBytes : targetStats . bytesWritten ,
622661 trgRxBytes : targetStats . bytesRead ,
623662 } ;
0 commit comments