public void Initialize()
        {
            _expectedProcessCount = 0;
            _tempFile             = Path.GetTempFileName();
            _mockHttp             = new MockHttpMessageHandler();
            _client = new HttpClient(_mockHttp);

            _webApps = new Dictionary <string, WebAppConfig>
            {
                {
                    "fakeApp",
                    new WebAppConfig("1234")
                    {
                        SubDomain = "fake-app",
                        HostName  = "dev.fake-app.com",
                        Region    = "us"
                    }
                }
            };

            _mockErrorDisplay = new Mock <IErrorDisplayFunc>();
            _mockErrorDisplay.Setup(x => x.ShowError(It.IsAny <string>()))
            .Returns(Task.FromResult(0))
            .Verifiable("Error display not called.");

            InitializeUtils("ngrok version 2.3.34\r\n");

            _emptyTunnelsResponse = new NgrokTunnelsApiResponse
            {
                tunnels = new Tunnel[0],
                uri     = ""
            };

            _expectedRequest = new NgrokTunnelApiRequest
            {
                addr        = "localhost:1234",
                host_header = "localhost:1234",
                name        = "fakeApp",
                proto       = "http",
                subdomain   = "fake-app",
                hostname    = "dev.fake-app.com"
            };
        }
        public void Initialize()
        {
            _mockHttp = new MockHttpMessageHandler();
            _client   = new HttpClient(_mockHttp);

            _webApps = new Dictionary <string, WebAppConfig>
            {
                {
                    "fakeApp",
                    new WebAppConfig
                    {
                        PortNumber = 1234,
                        SubDomain  = "fake-app"
                    }
                }
            };

            _mockErrorDisplay = new Mock <IErrorDisplayFunc>();
            _mockErrorDisplay.Setup(x => x.ShowError(It.IsAny <string>()))
            .Returns(Task.FromResult(0))
            .Verifiable("Error display not called.");

            _ngrokProcess = new FakeNgrokProcess("");
            _utils        = new NgrokUtils(_webApps, "", _mockErrorDisplay.Object.ShowError, _client, _ngrokProcess);

            _emptyTunnelsResponse = new NgrokTunnelsApiResponse
            {
                tunnels = new Tunnel[0],
                uri     = ""
            };

            _expectedRequest = new NgrokTunnelApiRequest
            {
                addr        = "localhost:1234",
                host_header = "localhost:1234",
                name        = "fakeApp",
                proto       = "http",
                subdomain   = "fake-app"
            };
        }
        private async Task <Tunnel> CreateTunnelAsync(string projectName, string addr, bool retry = false)
        {
            if (string.IsNullOrEmpty(addr))
            {
                addr = "80";
            }
            else
            {
                int x;
                if (!int.TryParse(addr, out x))
                {
                    var url = new Uri(addr);
                    if (url.Port != 80 && url.Port != 443)
                    {
                        addr = $"{url.Host}:{url.Port}";
                    }
                    else
                    {
                        if (addr.StartsWith("http://"))
                        {
                            addr = addr.Remove(addr.IndexOf("http://"), "http://".Length);
                        }
                        if (addr.StartsWith("https://"))
                        {
                            addr = addr.Remove(addr.IndexOf("https://"), "https://".Length);
                        }
                    }
                }
            }

            var request = new NgrokTunnelApiRequest
            {
                name        = projectName,
                addr        = addr,
                proto       = "http",
                host_header = addr
            };

            // TODO fix later once I bring back support for ngrok configs
            //if (!string.IsNullOrEmpty(_webAppConfig.SubDomain))
            //{
            //	request.subdomain = _webAppConfig.SubDomain;
            //}

            Debug.WriteLine($"request: '{JsonConvert.SerializeObject(request)}'");
            var json        = JsonConvert.SerializeObject(request);
            var httpContent = new StringContent(json, Encoding.UTF8, "application/json");
            var response    = await _ngrokApi.PostAsync("/api/tunnels", httpContent);

            if (!response.IsSuccessStatusCode)
            {
                var errorText = await response.Content.ReadAsStringAsync();

                Debug.WriteLine($"{response.StatusCode} errorText: '{errorText}'");
                NgrokErrorApiResult error;

                try
                {
                    error = JsonConvert.DeserializeObject <NgrokErrorApiResult>(errorText);
                }
                catch (JsonReaderException)
                {
                    error = null;
                }

                if (error != null)
                {
                    _logger.Log(LogLevel.Error, $"Could not create tunnel for {projectName} ({addr}): " +
                                $"\n[{error.error_code}] {error.msg}" +
                                $"\nDetails: {error.details.err.Replace("\\n", "\n")}");
                }
                else
                {
                    if (retry)
                    {
                        _logger.Log(LogLevel.Error, $"Could not create tunnel for {projectName} ({addr}): " +
                                    $"\n{errorText}");
                    }
                    else
                    {
                        await Task.Delay(1000);                          // wait for ngrok to spin up completely?
                        await CreateTunnelAsync(projectName, addr, true);
                    }
                }
                return(null);
            }

            var responseText = await response.Content.ReadAsStringAsync();

            Debug.WriteLine($"responseText: '{responseText}'");
            return(JsonConvert.DeserializeObject <Tunnel>(responseText));
        }