Skip to content

Commit

Permalink
Add port validation checks for HTTP streaming (#315)
Browse files Browse the repository at this point in the history
* basic working prototype

* cleaner implementation

* typing fixes + removed logs

* removed logs

* trying random port

* port variables

* checking only 25 ports

---------

Co-authored-by: Victoria Hall <[email protected]>
  • Loading branch information
hallvictoria and Victoria Hall authored Jan 21, 2025
1 parent cc3613c commit dd5912c
Showing 1 changed file with 55 additions and 1 deletion.
56 changes: 55 additions & 1 deletion src/http/httpProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
import { serialize as serializeCookie } from 'cookie';
import { EventEmitter } from 'events';
import * as http from 'http';
import * as net from 'net';
import { AzFuncSystemError, ensureErrorType } from '../errors';
import { nonNullProp } from '../utils/nonNull';
import { workerSystemLog } from '../utils/workerSystemLog';
import { HttpResponse } from './HttpResponse';

const requests: Record<string, http.IncomingMessage> = {};
const responses: Record<string, http.ServerResponse> = {};
const minPort = 55000;
const maxPort = 55025;

const invocRequestEmitter = new EventEmitter();

Expand Down Expand Up @@ -105,8 +108,24 @@ export async function setupHttpProxy(): Promise<string> {

server.listen(() => {
const address = server.address();
// Valid address has been created
if (address !== null && typeof address === 'object') {
resolve(`http://localhost:${address.port}/`);
if (address.port === 0) {
// Auto-assigned port is 0, find and bind to an open port
workerSystemLog('debug', `Port 0 assigned. Finding open port.`);
findOpenPort((openPort: number) => {
// Close the server and re-listen on the found open port
server.close();
server.listen(openPort, () => {
workerSystemLog('debug', `Server is now listening on found open port: ${openPort}`);
});
resolve(`http://localhost:${openPort}/`);
});
} else {
// Auto-assigned port is not 0
workerSystemLog('debug', `Auto-assigned port is valid. Port: ${address.port}`);
resolve(`http://localhost:${address.port}/`);
}
} else {
reject(new AzFuncSystemError('Unexpected server address during http proxy setup'));
}
Expand All @@ -117,3 +136,38 @@ export async function setupHttpProxy(): Promise<string> {
});
});
}

// Function to find an open port starting from a specified port
function findOpenPort(callback: (port: number) => void): void {
const server = net.createServer();

function tryPort(port: number) {
if (port > maxPort) {
// If we've reached the maximum port, throw an error
throw new AzFuncSystemError(
`No available ports found between ${minPort} and ${maxPort}. To enable HTTP streaming, please open a port in this range.`
);
}

server.once('error', () => {
// If the port is unavailable, increment and try the next one
tryPort(port + 1);
});

// If the port is available, return it
server.once('listening', () => {
const address = server.address();
if (address !== null && typeof address === 'object') {
port = address.port;
server.close();
callback(port);
}
});

// Try binding to the given port
server.listen(port);
}

// Start trying from the specified starting port
tryPort(minPort);
}

0 comments on commit dd5912c

Please sign in to comment.