package main import ( "encoding/json" "fmt" "net" "net/http" "net/url" "time" ) type CautiousHTTPClient interface { Get(string) (*http.Response, error) GetJSON(string, interface{}) error } type cautiousHttpClient struct { client *http.Client } func NewCautiousHTTPClient() CautiousHTTPClient { // May Need: TLSClientConfig *tls.Config CautiousTransport := &http.Transport{ Proxy: http.ProxyFromEnvironment, DialContext: (&net.Dialer{ Timeout: 1 * time.Second, KeepAlive: 30 * time.Second, DualStack: true, }).DialContext, MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, TLSHandshakeTimeout: 1 * time.Second, ExpectContinueTimeout: 1 * time.Second, ResponseHeaderTimeout: 10 * time.Second, MaxResponseHeaderBytes: 500000, // .5 MB } return &cautiousHttpClient{ client: &http.Client{ Transport: CautiousTransport, Timeout: 30 * time.Second, }, } } func (c *cautiousHttpClient) Get(gurl string) (*http.Response, error) { u, err := url.Parse(gurl) if err != nil { return nil, err } // TODO if u.Scheme != "https" && false { return nil, fmt.Errorf("URL for GET must be secure") } r, err := c.client.Get(u.String()) if err != nil { return nil, err } r.Body = http.MaxBytesReader(nil, r.Body, 1000000) return r, err } func (c *cautiousHttpClient) GetJSON(url string, rv interface{}) error { r, err := c.Get(url) if err != nil { return err } defer r.Body.Close() d := json.NewDecoder(r.Body) err = d.Decode(rv) if err != nil { return err } return nil }