diff --git a/frontend/lgproxy.go b/frontend/lgproxy.go index e7c08e7..04e24a3 100644 --- a/frontend/lgproxy.go +++ b/frontend/lgproxy.go @@ -2,6 +2,7 @@ package main import ( "io" + "net" "net/http" "net/url" "strconv" @@ -14,6 +15,23 @@ type channelData struct { data string } +func createConnectionTimeoutRoundTripper(timeout int) http.RoundTripper { + context := net.Dialer{ + Timeout: time.Duration(timeout) * time.Second, + } + return &http.Transport{ + DialContext: context.DialContext, + + // Default options from transport.go + Proxy: http.ProxyFromEnvironment, + ForceAttemptHTTP2: true, + MaxIdleConns: 100, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 10 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + } +} + // Send commands to lgproxy instances in parallel, and retrieve their responses func batchRequest(servers []string, endpoint string, command string) []string { // Channel and array for storing responses @@ -47,7 +65,9 @@ func batchRequest(servers []string, endpoint string, command string) []string { } url := "http://" + hostname + ":" + strconv.Itoa(setting.proxyPort) + "/" + url.PathEscape(endpoint) + "?q=" + url.QueryEscape(command) go func(url string, i int) { - client := http.Client{Timeout: time.Duration(setting.timeOut) * time.Second} + client := http.Client{ + Transport: createConnectionTimeoutRoundTripper(setting.connectionTimeOut), + Timeout: time.Duration(setting.timeOut) * time.Second} response, err := client.Get(url) if err != nil { ch <- channelData{i, "request failed: " + err.Error() + "\n"} diff --git a/frontend/main.go b/frontend/main.go index 55cd4f7..c30393b 100644 --- a/frontend/main.go +++ b/frontend/main.go @@ -7,24 +7,25 @@ import ( ) type settingType struct { - servers []string - serversDisplay []string - domain string - proxyPort int - whoisServer string - listen string - dnsInterface string - netSpecificMode string - titleBrand string - navBarBrand string - navBarBrandURL string - navBarAllServer string - navBarAllURL string - bgpmapInfo string - telegramBotName string - protocolFilter []string - nameFilter string - timeOut int + servers []string + serversDisplay []string + domain string + proxyPort int + whoisServer string + listen string + dnsInterface string + netSpecificMode string + titleBrand string + navBarBrand string + navBarBrandURL string + navBarAllServer string + navBarAllURL string + bgpmapInfo string + telegramBotName string + protocolFilter []string + nameFilter string + timeOut int + connectionTimeOut int } var setting settingType diff --git a/frontend/settings.go b/frontend/settings.go index d18d10a..4c4d1fd 100644 --- a/frontend/settings.go +++ b/frontend/settings.go @@ -9,23 +9,24 @@ import ( ) type viperSettingType struct { - Servers string `mapstructure:"servers"` - Domain string `mapstructure:"domain"` - ProxyPort int `mapstructure:"proxy_port"` - WhoisServer string `mapstructure:"whois"` - Listen string `mapstructure:"listen"` - DNSInterface string `mapstructure:"dns_interface"` - NetSpecificMode string `mapstructure:"net_specific_mode"` - TitleBrand string `mapstructure:"title_brand"` - NavBarBrand string `mapstructure:"navbar_brand"` - NavBarBrandURL string `mapstructure:"navbar_brand_url"` - NavBarAllServer string `mapstructure:"navbar_all_servers"` - NavBarAllURL string `mapstructure:"navbar_all_url"` - BgpmapInfo string `mapstructure:"bgpmap_info"` - TelegramBotName string `mapstructure:"telegram_bot_name"` - ProtocolFilter string `mapstructure:"protocol_filter"` - NameFilter string `mapstructure:"name_filter"` - TimeOut int `mapstructure:"timeout"` + Servers string `mapstructure:"servers"` + Domain string `mapstructure:"domain"` + ProxyPort int `mapstructure:"proxy_port"` + WhoisServer string `mapstructure:"whois"` + Listen string `mapstructure:"listen"` + DNSInterface string `mapstructure:"dns_interface"` + NetSpecificMode string `mapstructure:"net_specific_mode"` + TitleBrand string `mapstructure:"title_brand"` + NavBarBrand string `mapstructure:"navbar_brand"` + NavBarBrandURL string `mapstructure:"navbar_brand_url"` + NavBarAllServer string `mapstructure:"navbar_all_servers"` + NavBarAllURL string `mapstructure:"navbar_all_url"` + BgpmapInfo string `mapstructure:"bgpmap_info"` + TelegramBotName string `mapstructure:"telegram_bot_name"` + ProtocolFilter string `mapstructure:"protocol_filter"` + NameFilter string `mapstructure:"name_filter"` + TimeOut int `mapstructure:"timeout"` + ConnectionTimeOut int `mapstructure:"connection_timeout"` } // Parse settings with viper, and convert to legacy setting format @@ -87,9 +88,12 @@ func parseSettings() { pflag.String("name-filter", "", "protocol name regex to hide in summary tables (RE2 syntax); defaults to none if not set") viper.BindPFlag("name_filter", pflag.Lookup("name-filter")) - pflag.Int("time-out", 120, "time before request timed out, in seconds; defaults to 120 if not set") + pflag.Int("time-out", 120, "time before backend HTTP request times out, in seconds; defaults to 120 if not set") viper.BindPFlag("timeout", pflag.Lookup("time-out")) + pflag.Int("connection-time-out", 5, "time before backend TCP connection times out, in seconds; defaults to 5 if not set") + viper.BindPFlag("connection_timeout", pflag.Lookup("connection-time-out")) + pflag.Parse() if err := viper.ReadInConfig(); err != nil { @@ -139,6 +143,7 @@ func parseSettings() { setting.nameFilter = viperSettings.NameFilter setting.timeOut = viperSettings.TimeOut + setting.connectionTimeOut = viperSettings.ConnectionTimeOut fmt.Printf("%#v\n", setting) }