function createRunCommand()

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}`);
      });
  }
}