Skip to content

Commit e035023

Browse files
author
Victoria Hall
committed
basic working prototype
1 parent 4b36578 commit e035023

File tree

1 file changed

+50
-5
lines changed

1 file changed

+50
-5
lines changed

src/http/httpProxy.ts

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import { serialize as serializeCookie } from 'cookie';
55
import { EventEmitter } from 'events';
66
import * as http from 'http';
7+
import * as net from 'net';
78
import { AzFuncSystemError, ensureErrorType } from '../errors';
89
import { nonNullProp } from '../utils/nonNull';
910
import { workerSystemLog } from '../utils/workerSystemLog';
@@ -16,13 +17,16 @@ const invocRequestEmitter = new EventEmitter();
1617

1718
export 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

3539
const invocationIdHeader = 'x-ms-invocation-id';
3640
export 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
8694
export 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

Comments
 (0)