4
4
import { serialize as serializeCookie } from 'cookie' ;
5
5
import { EventEmitter } from 'events' ;
6
6
import * as http from 'http' ;
7
+ import * as net from 'net' ;
7
8
import { AzFuncSystemError , ensureErrorType } from '../errors' ;
8
9
import { nonNullProp } from '../utils/nonNull' ;
9
10
import { workerSystemLog } from '../utils/workerSystemLog' ;
10
11
import { HttpResponse } from './HttpResponse' ;
11
12
12
13
const requests : Record < string , http . IncomingMessage > = { } ;
13
14
const responses : Record < string , http . ServerResponse > = { } ;
15
+ const minPort = 55000 ;
16
+ const maxPort = 55025 ;
14
17
15
18
const invocRequestEmitter = new EventEmitter ( ) ;
16
19
@@ -105,8 +108,24 @@ export async function setupHttpProxy(): Promise<string> {
105
108
106
109
server . listen ( ( ) => {
107
110
const address = server . address ( ) ;
111
+ // Valid address has been created
108
112
if ( address !== null && typeof address === 'object' ) {
109
- resolve ( `http://localhost:${ address . port } /` ) ;
113
+ if ( address . port === 0 ) {
114
+ // Auto-assigned port is 0, find and bind to an open port
115
+ workerSystemLog ( 'debug' , `Port 0 assigned. Finding open port.` ) ;
116
+ findOpenPort ( ( openPort : number ) => {
117
+ // Close the server and re-listen on the found open port
118
+ server . close ( ) ;
119
+ server . listen ( openPort , ( ) => {
120
+ workerSystemLog ( 'debug' , `Server is now listening on found open port: ${ openPort } ` ) ;
121
+ } ) ;
122
+ resolve ( `http://localhost:${ openPort } /` ) ;
123
+ } ) ;
124
+ } else {
125
+ // Auto-assigned port is not 0
126
+ workerSystemLog ( 'debug' , `Auto-assigned port is valid. Port: ${ address . port } ` ) ;
127
+ resolve ( `http://localhost:${ address . port } /` ) ;
128
+ }
110
129
} else {
111
130
reject ( new AzFuncSystemError ( 'Unexpected server address during http proxy setup' ) ) ;
112
131
}
@@ -117,3 +136,38 @@ export async function setupHttpProxy(): Promise<string> {
117
136
} ) ;
118
137
} ) ;
119
138
}
139
+
140
+ // Function to find an open port starting from a specified port
141
+ function findOpenPort ( callback : ( port : number ) => void ) : void {
142
+ const server = net . createServer ( ) ;
143
+
144
+ function tryPort ( port : number ) {
145
+ if ( port > maxPort ) {
146
+ // If we've reached the maximum port, throw an error
147
+ throw new AzFuncSystemError (
148
+ `No available ports found between ${ minPort } and ${ maxPort } . To enable HTTP streaming, please open a port in this range.`
149
+ ) ;
150
+ }
151
+
152
+ server . once ( 'error' , ( ) => {
153
+ // If the port is unavailable, increment and try the next one
154
+ tryPort ( port + 1 ) ;
155
+ } ) ;
156
+
157
+ // If the port is available, return it
158
+ server . once ( 'listening' , ( ) => {
159
+ const address = server . address ( ) ;
160
+ if ( address !== null && typeof address === 'object' ) {
161
+ port = address . port ;
162
+ server . close ( ) ;
163
+ callback ( port ) ;
164
+ }
165
+ } ) ;
166
+
167
+ // Try binding to the given port
168
+ server . listen ( port ) ;
169
+ }
170
+
171
+ // Start trying from the specified starting port
172
+ tryPort ( minPort ) ;
173
+ }
0 commit comments