diff options
author | René 'Necoro' Neumann <necoro@necoro.eu> | 2020-05-04 15:31:46 +0200 |
---|---|---|
committer | René 'Necoro' Neumann <necoro@necoro.eu> | 2020-05-04 15:31:46 +0200 |
commit | e2322c799ae0a05ed2b7eb63bffebbe0b54b292f (patch) | |
tree | 9f72634c0f1525a514caa7d51e33c4dc8b5a137f /internal/http/client.go | |
parent | 44f53f5956216cdd52ad58d6e666013a8f202967 (diff) | |
download | feed2imap-go-e2322c799ae0a05ed2b7eb63bffebbe0b54b292f.tar.gz feed2imap-go-e2322c799ae0a05ed2b7eb63bffebbe0b54b292f.tar.bz2 feed2imap-go-e2322c799ae0a05ed2b7eb63bffebbe0b54b292f.zip |
Unify connection handling
Diffstat (limited to 'internal/http/client.go')
-rw-r--r-- | internal/http/client.go | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/internal/http/client.go b/internal/http/client.go new file mode 100644 index 0000000..c9af26e --- /dev/null +++ b/internal/http/client.go @@ -0,0 +1,88 @@ +package http + +import ( + ctxt "context" + "crypto/tls" + "fmt" + "net/http" + "time" +) + +// share HTTP clients +var ( + stdClient *http.Client + unsafeClient *http.Client +) + +// Error represents an HTTP error returned by a server. +type Error struct { + StatusCode int + Status string +} + +func (err Error) Error() string { + return fmt.Sprintf("http error: %s", err.Status) +} + +func init() { + // std + stdClient = &http.Client{Transport: http.DefaultTransport} + + // unsafe + tlsConfig := &tls.Config{InsecureSkipVerify: true} + transport := http.DefaultTransport.(*http.Transport).Clone() + transport.TLSClientConfig = tlsConfig + unsafeClient = &http.Client{Transport: transport} +} + +func context(timeout int) (ctxt.Context, ctxt.CancelFunc) { + return ctxt.WithTimeout(ctxt.Background(), time.Duration(timeout)*time.Second) +} + +func client(disableTLS bool) *http.Client { + if disableTLS { + return unsafeClient + } + return stdClient +} + +var noop ctxt.CancelFunc = func() {} + +func Get(url string, timeout int, disableTLS bool) (resp *http.Response, cancel ctxt.CancelFunc, err error) { + prematureExit := true + ctx, ctxCancel := context(timeout) + + cancel = func() { + if resp != nil { + _ = resp.Body.Close() + } + ctxCancel() + } + + defer func() { + if prematureExit { + cancel() + } + }() + + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return nil, noop, err + } + req.Header.Set("User-Agent", "Feed2Imap-Go/1.0") + + resp, err = client(disableTLS).Do(req) + if err != nil { + return nil, noop, err + } + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return nil, noop, Error{ + StatusCode: resp.StatusCode, + Status: resp.Status, + } + } + + prematureExit = false + return resp, cancel, nil +} |