in tools/awps-tunnel/server/commander.ts [238:383]
function createRunCommand(run: Command, dbFile: string, settings: Settings, command: RunCommandLineArgs) {
if (command.verbose) {
printer.enableVerboseLogging();
setLogLevel("verbose");
} else {
setLogLevel("info");
}
const hub = command.hub ?? settings.WebPubSub.Hub;
if (!hub) {
printer.error(`Error: hub is neither specified nor binded. Use --hub to specify the hub.`);
run.outputHelp();
return;
}
const subscription = command.subscription ?? settings.WebPubSub.SubscriptionId;
const resourceGroup = command.resourceGroup ?? settings.WebPubSub.ResourceGroup;
let currentUpstream = command.upstream ?? settings.WebPubSub.Upstream;
let upstream: URL;
if (currentUpstream) {
const parsed = parseUrl(currentUpstream, "http");
if (!parsed) {
printer.error(`Error: invalid upstream: ${currentUpstream}. Use -u|--upstream to specify the upstream URL.`);
return;
}
upstream = parsed;
currentUpstream = parsed.toString();
} else {
printer.status(`Upstream is not specified. http://localhost:3000 is used as the default upstream value. Use -u|--upstream to specify the upstream URL.`);
currentUpstream = "http://localhost:3000";
upstream = new URL(currentUpstream);
}
// --connection > --endpoint > env WebPubSubConnectionString > binded settings.WebPubSub.Endpoint
let connectionString: string | undefined = undefined;
let endpoint: string | undefined = undefined;
if (command.connection) {
if (command.endpoint) {
printer.warn(`Warning: both --connection and --endpoint are set, --connection will be used.`);
} else {
printer.status(`Using connection string specified using --connection.`);
}
connectionString = command.connection;
} else {
if (command.endpoint) {
// override the endpoint value if it is set from the command directly
if (!parseUrl(command.endpoint)) {
printer.error(`Error: invalid endpoint: ${command.endpoint}`);
return;
}
if (process.env.WebPubSubConnectionString) {
printer.warn(`Warning: both --endpoint and env WebPubSubConnectionString are set, --endpoint will be used.`);
} else {
printer.status(`Using endpoint specified using --endpoint.`);
}
endpoint = command.endpoint;
} else {
connectionString = process.env.WebPubSubConnectionString;
if (connectionString) {
printer.status(`Using connection string from env WebPubSubConnectionString.`);
} else {
endpoint = settings.WebPubSub.Endpoint;
if (endpoint) {
printer.status(`Using endpoint ${endpoint} from binded settings. Please make sure the Access Policy is correctly configured to allow your access.`);
} else {
printer.error(`Error: SET WebPubSubConnectionString env or specify --endpoint <endpoint> or specify --connection <connectionString>`);
run.outputHelp();
return;
}
}
}
}
let tunnel: HttpServerProxy;
if (connectionString) {
tunnel = HttpServerProxy.fromConnectionString(connectionString, hub, { target: currentUpstream });
} else {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
tunnel = new HttpServerProxy(endpoint!, getCredential(), hub, { target: currentUpstream });
}
const app = express();
const server = createServer(app);
printer.status(`Connecting to ${tunnel.endpoint}, hub: ${tunnel.hub}, upstream: ${currentUpstream}`);
const dataHub = new DataHub(server, tunnel, upstream, dbFile);
dataHub.ReportStatusChange(ConnectionStatus.Connecting);
reportServiceConfiguration(dataHub, subscription, resourceGroup, new URL(tunnel.endpoint), tunnel.hub);
tunnel
.runAsync({
handleProxiedRequest: async (request, time, proxiedUrl, invoke) => {
const item: HttpHistoryItem = {
methodName: request.HttpMethod,
url: proxiedUrl.toString(),
requestRaw: dumpRawRequest(proxiedUrl, request),
requestAtOffset: time,
unread: true,
};
await dataHub.AddTraffic(item);
printer.log(`[${new Date(time).toISOString()}]Proxy request to ${proxiedUrl.toString()}`);
const response = await invoke();
printer.log(`[${new Date().toISOString()}]Get response ${proxiedUrl}: ${response.StatusCode}`);
if (response.StatusCode < 400) {
dataHub.ReportTunnelToLocalServerStatus(ConnectionStatusPairs.Connected);
} else {
dataHub.ReportTunnelToLocalServerStatus(ConnectionStatusPairs.ErrorResponse);
}
item.code = response.StatusCode;
item.responseRaw = getRawResponse(response);
dataHub.UpdateTraffic(item);
return response;
},
})
.then(() => {
printer.status(`Established tunnel connection ${tunnel.id}.`);
dataHub.ReportStatusChange(ConnectionStatus.Connected);
})
.catch((err) => {
printer.error(`Error establishing tunnel connection: ${err}. Please make sure the Access Policy is correctly configured to allow your access.`);
dataHub.ReportStatusChange(ConnectionStatus.Disconnected);
});
const upstreamPort = tryParseInt(upstream.port) ?? 80;
if (!command.noWebview) {
const webviewHost = command.webviewHost ?? settings.WebPubSub.WebviewHost ?? "127.0.0.1";
const webviewPort = command.webviewPort ?? settings.WebPubSub.WebviewPort ?? process.env.AWPS_TUNNEL_SERVER_PORT;
let port: number | undefined = upstreamPort + 1000;
if (webviewPort) {
port = tryParseInt(webviewPort);
if (!port) {
printer.error(`Error: invalid webview port: ${port}`);
return;
}
}
app.use(express.static(path.join(__dirname, "../client/build")));
server
.listen(port, webviewHost, () => {
printer.text(`Open webview at: http://${webviewHost}:${port}`);
})
.on("error", (err) => {
printer.error(`Error on starting webview server: ${err}`);
});
}
}