44import { serialize as serializeCookie } from 'cookie' ;
55import { EventEmitter } from 'events' ;
66import * as http from 'http' ;
7+ import * as net from 'net' ;
78import { AzFuncSystemError , ensureErrorType } from '../errors' ;
89import { nonNullProp } from '../utils/nonNull' ;
910import { workerSystemLog } from '../utils/workerSystemLog' ;
@@ -16,13 +17,16 @@ const invocRequestEmitter = new EventEmitter();
1617
1718export async function waitForProxyRequest ( invocationId : string ) : Promise < http . IncomingMessage > {
1819 return new Promise ( ( resolve , _reject ) => {
20+ workerSystemLog ( 'debug' , 'Waiting for proxy request' , { invocationId } ) ;
1921 const req = requests [ invocationId ] ;
2022 if ( req ) {
2123 resolve ( req ) ;
24+ workerSystemLog ( 'debug' , 'Proxy request found' , { invocationId } ) ;
2225 delete requests [ invocationId ] ;
2326 } else {
2427 invocRequestEmitter . once ( invocationId , ( ) => {
2528 const req = requests [ invocationId ] ;
29+ workerSystemLog ( 'debug' , 'Proxy request else statement' ) ;
2630 if ( req ) {
2731 resolve ( req ) ;
2832 delete requests [ invocationId ] ;
@@ -34,11 +38,13 @@ export async function waitForProxyRequest(invocationId: string): Promise<http.In
3438
3539const invocationIdHeader = 'x-ms-invocation-id' ;
3640export async function sendProxyResponse ( invocationId : string , userRes : HttpResponse ) : Promise < void > {
41+ workerSystemLog ( 'debug' , 'Sending proxy response' , { invocationId } ) ;
3742 const proxyRes = nonNullProp ( responses , invocationId ) ;
3843 delete responses [ invocationId ] ;
3944 for ( const [ key , val ] of userRes . headers . entries ( ) ) {
4045 proxyRes . setHeader ( key , val ) ;
4146 }
47+ workerSystemLog ( 'debug' , 'Http proxy headers set' ) ;
4248 proxyRes . setHeader ( invocationIdHeader , invocationId ) ;
4349 proxyRes . statusCode = userRes . status ;
4450
@@ -48,7 +54,9 @@ export async function sendProxyResponse(invocationId: string, userRes: HttpRespo
4854
4955 if ( userRes . body ) {
5056 for await ( const chunk of userRes . body . values ( ) ) {
57+ workerSystemLog ( 'debug' , 'Writing proxy response chunk' ) ;
5158 proxyRes . write ( chunk ) ;
59+ workerSystemLog ( 'debug' , 'Http proxy response chunks written' ) ;
5260 }
5361 }
5462 proxyRes . end ( ) ;
@@ -86,10 +94,12 @@ function setCookies(userRes: HttpResponse, proxyRes: http.ServerResponse): void
8694export async function setupHttpProxy ( ) : Promise < string > {
8795 return new Promise ( ( resolve , reject ) => {
8896 const server = http . createServer ( ) ;
97+ workerSystemLog ( 'debug' , 'Http proxy server created' ) ;
8998
9099 server . on ( 'request' , ( req , res ) => {
91100 const invocationId = req . headers [ invocationIdHeader ] ;
92101 if ( typeof invocationId === 'string' ) {
102+ workerSystemLog ( 'debug' , 'Http proxy request received' , { invocationId } ) ;
93103 requests [ invocationId ] = req ;
94104 responses [ invocationId ] = res ;
95105 invocRequestEmitter . emit ( invocationId ) ;
@@ -103,12 +113,22 @@ export async function setupHttpProxy(): Promise<string> {
103113 workerSystemLog ( 'error' , `Http proxy error: ${ err . stack || err . message } ` ) ;
104114 } ) ;
105115
106- server . listen ( ( ) => {
107- const address = server . address ( ) ;
108- if ( address !== null && typeof address === 'object' ) {
109- resolve ( `http://localhost:${ address . port } /` ) ;
116+ server . listen ( 0 , ( ) => {
117+ workerSystemLog ( 'debug' , `VICTORIA: auto-assigned port: ${ server . address ( ) . port } ` ) ;
118+
119+ // If port is still 0, find and bind to an open port
120+ if ( server . address ( ) . port === 0 ) {
121+ workerSystemLog ( 'debug' , `VICTORIA: Port 0 assigned. Finding open port.` ) ;
122+ findOpenPort ( 51929 , ( openPort ) => {
123+ workerSystemLog ( 'debug' , `VICTORIA: found open port: ${ openPort } ` ) ;
124+ server . close ( ) ; // Close the server
125+ server . listen ( openPort , ( ) => {
126+ workerSystemLog ( 'debug' , `VICTORIA: server is now listening on found open port: ${ openPort } ` ) ;
127+ } ) ;
128+ resolve ( `http://localhost:${ openPort } /` ) ;
129+ } ) ;
110130 } else {
111- reject ( new AzFuncSystemError ( 'Unexpected server address during http proxy setup' ) ) ;
131+ resolve ( `http://localhost: ${ server . address ( ) . port } /` ) ;
112132 }
113133 } ) ;
114134
@@ -117,3 +137,28 @@ export async function setupHttpProxy(): Promise<string> {
117137 } ) ;
118138 } ) ;
119139}
140+
141+
142+ // Function to find an open port starting from a specified port
143+ function findOpenPort ( startingPort , callback ) {
144+ const server = net . createServer ( ) ;
145+
146+ function tryPort ( port ) {
147+ server . once ( 'error' , ( ) => {
148+ // If the port is unavailable, increment and try the next one
149+ tryPort ( port + 1 ) ;
150+ } ) ;
151+
152+ server . once ( 'listening' , ( ) => {
153+ const port = server . address ( ) . port ;
154+ server . close ( ) ;
155+ callback ( port ) ;
156+ } ) ;
157+
158+ // Try binding to the given port
159+ server . listen ( port ) ;
160+ }
161+
162+ // Start trying from the specified starting port
163+ tryPort ( startingPort ) ;
164+ }
0 commit comments