Repository: xenolf/lego
Pull request #580 (2018-06-16 01:33:01)

Review DNS providers
- create `log.Infof` and `log.Warnf`
- use one `http.Client` by provider instead of one client by request
- use the same receiver name `d` for all `DNSProvider`
- use `http.MethodXXX`



Patch:
diff --git a/acme/client.go b/acme/client.go
index 6e4c9d5f..ebfd11a2 100644
--- a/acme/client.go
+++ b/acme/client.go
@@ -164,7 +164,7 @@ func (c *Client) Register(tosAgreed bool) (*RegistrationResource, error) {
 	if c == nil || c.user == nil {
 		return nil, errors.New("acme: cannot register a nil client or user")
 	}
-	log.Printf("[INFO] acme: Registering account for %s", c.user.GetEmail())
+	log.Infof("acme: Registering account for %s", c.user.GetEmail())
 
 	accMsg := accountMessage{}
 	if c.user.GetEmail() != "" {
@@ -198,7 +198,7 @@ func (c *Client) RegisterWithExternalAccountBinding(tosAgreed bool, kid string,
 	if c == nil || c.user == nil {
 		return nil, errors.New("acme: cannot register a nil client or user")
 	}
-	log.Printf("[INFO] acme: Registering account (EAB) for %s", c.user.GetEmail())
+	log.Infof("acme: Registering account (EAB) for %s", c.user.GetEmail())
 
 	accMsg := accountMessage{}
 	if c.user.GetEmail() != "" {
@@ -244,7 +244,7 @@ func (c *Client) RegisterWithExternalAccountBinding(tosAgreed bool, kid string,
 // ResolveAccountByKey will attempt to look up an account using the given account key
 // and return its registration resource.
 func (c *Client) ResolveAccountByKey() (*RegistrationResource, error) {
-	log.Printf("[INFO] acme: Trying to resolve account by key")
+	log.Infof("acme: Trying to resolve account by key")
 
 	acc := accountMessage{OnlyReturnExisting: true}
 	hdr, err := postJSON(c.jws, c.directory.NewAccountURL, acc, nil)
@@ -273,7 +273,7 @@ func (c *Client) DeleteRegistration() error {
 	if c == nil || c.user == nil {
 		return errors.New("acme: cannot unregister a nil client or user")
 	}
-	log.Printf("[INFO] acme: Deleting account for %s", c.user.GetEmail())
+	log.Infof("acme: Deleting account for %s", c.user.GetEmail())
 
 	accMsg := accountMessage{
 		Status: "deactivated",
@@ -293,7 +293,7 @@ func (c *Client) QueryRegistration() (*RegistrationResource, error) {
 		return nil, errors.New("acme: cannot query the registration of a nil client or user")
 	}
 	// Log the URL here instead of the email as the email may not be set
-	log.Printf("[INFO] acme: Querying account for %s", c.user.GetRegistration().URI)
+	log.Infof("acme: Querying account for %s", c.user.GetRegistration().URI)
 
 	accMsg := accountMessage{}
 
@@ -339,9 +339,9 @@ DNSNames:
 	}
 
 	if bundle {
-		log.Printf("[INFO][%s] acme: Obtaining bundled SAN certificate given a CSR", strings.Join(domains, ", "))
+		log.Infof("[%s] acme: Obtaining bundled SAN certificate given a CSR", strings.Join(domains, ", "))
 	} else {
-		log.Printf("[INFO][%s] acme: Obtaining SAN certificate given a CSR", strings.Join(domains, ", "))
+		log.Infof("[%s] acme: Obtaining SAN certificate given a CSR", strings.Join(domains, ", "))
 	}
 
 	order, err := c.createOrderForIdentifiers(domains)
@@ -363,7 +363,7 @@ DNSNames:
 		return nil, err
 	}
 
-	log.Printf("[INFO][%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
+	log.Infof("[%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
 
 	failures := make(ObtainError)
 	cert, err := c.requestCertificateForCsr(order, bundle, csr.Raw, nil)
@@ -399,9 +399,9 @@ func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto
 	}
 
 	if bundle {
-		log.Printf("[INFO][%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", "))
+		log.Infof("[%s] acme: Obtaining bundled SAN certificate", strings.Join(domains, ", "))
 	} else {
-		log.Printf("[INFO][%s] acme: Obtaining SAN certificate", strings.Join(domains, ", "))
+		log.Infof("[%s] acme: Obtaining SAN certificate", strings.Join(domains, ", "))
 	}
 
 	order, err := c.createOrderForIdentifiers(domains)
@@ -423,7 +423,7 @@ func (c *Client) ObtainCertificate(domains []string, bundle bool, privKey crypto
 		return nil, err
 	}
 
-	log.Printf("[INFO][%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
+	log.Infof("[%s] acme: Validations succeeded; requesting certificates", strings.Join(domains, ", "))
 
 	failures := make(ObtainError)
 	cert, err := c.requestCertificateForOrder(order, bundle, privKey, mustStaple)
@@ -482,7 +482,7 @@ func (c *Client) RenewCertificate(cert CertificateResource, bundle, mustStaple b
 
 	// This is just meant to be informal for the user.
 	timeLeft := x509Cert.NotAfter.Sub(time.Now().UTC())
-	log.Printf("[INFO][%s] acme: Trying renewal with %d hours remaining", cert.Domain, int(timeLeft.Hours()))
+	log.Infof("[%s] acme: Trying renewal with %d hours remaining", cert.Domain, int(timeLeft.Hours()))
 
 	// We always need to request a new certificate to renew.
 	// Start by checking to see if the certificate was based off a CSR, and
@@ -556,7 +556,7 @@ func (c *Client) solveChallengeForAuthz(authorizations []authorization) error {
 	for _, authz := range authorizations {
 		if authz.Status == "valid" {
 			// Boulder might recycle recent validated authz (see issue #267)
-			log.Printf("[INFO][%s] acme: Authorization already valid; skipping challenge", authz.Identifier.Value)
+			log.Infof("[%s] acme: Authorization already valid; skipping challenge", authz.Identifier.Value)
 			continue
 		}
 
@@ -587,7 +587,7 @@ func (c *Client) chooseSolver(auth authorization, domain string) (int, solver) {
 		if solver, ok := c.solvers[Challenge(challenge.Type)]; ok {
 			return i, solver
 		}
-		log.Printf("[INFO][%s] acme: Could not find solver for: %s", domain, challenge.Type)
+		log.Infof("[%s] acme: Could not find solver for: %s", domain, challenge.Type)
 	}
 	return 0, nil
 }
@@ -639,7 +639,7 @@ func (c *Client) getAuthzForOrder(order orderResource) ([]authorization, error)
 
 func logAuthz(order orderResource) {
 	for i, auth := range order.Authorizations {
-		log.Printf("[INFO][%s] AuthURL: %s", order.Identifiers[i].Value, auth)
+		log.Infof("[%s] AuthURL: %s", order.Identifiers[i].Value, auth)
 	}
 }
 
@@ -756,7 +756,7 @@ func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResou
 
 			if err != nil {
 				// If we fail to acquire the issuer cert, return the issued certificate - do not fail.
-				log.Printf("[WARNING][%s] acme: Could not bundle issuer certificate: %v", certRes.Domain, err)
+				log.Warnf("[%s] acme: Could not bundle issuer certificate: %v", certRes.Domain, err)
 			} else {
 				issuerCert = pemEncode(derCertificateBytes(issuerCert))
 
@@ -773,21 +773,21 @@ func (c *Client) checkCertResponse(order orderMessage, certRes *CertificateResou
 		certRes.Certificate = cert
 		certRes.CertURL = order.Certificate
 		certRes.CertStableURL = order.Certificate
-		log.Printf("[INFO][%s] Server responded with a certificate.", certRes.Domain)
+		log.Infof("[%s] Server responded with a certificate.", certRes.Domain)
 		return true, nil
 
 	case "processing":
 		return false, nil
 	case "invalid":
-		return false, errors.New("Order has invalid state: invalid")
+		return false, errors.New("order has invalid state: invalid")
+	default:
+		return false, nil
 	}
-
-	return false, nil
 }
 
 // getIssuerCertificate requests the issuer certificate
 func (c *Client) getIssuerCertificate(url string) ([]byte, error) {
-	log.Printf("[INFO] acme: Requesting issuer cert from %s", url)
+	log.Infof("acme: Requesting issuer cert from %s", url)
 	resp, err := httpGet(url)
 	if err != nil {
 		return nil, err
@@ -841,7 +841,7 @@ func validate(j *jws, domain, uri string, c challenge) error {
 	for {
 		switch chlng.Status {
 		case "valid":
-			log.Printf("[INFO][%s] The server validated our request", domain)
+			log.Infof("[%s] The server validated our request", domain)
 			return nil
 		case "pending":
 		case "processing":
diff --git a/acme/dns_challenge.go b/acme/dns_challenge.go
index d494501c..c8a35eb8 100644
--- a/acme/dns_challenge.go
+++ b/acme/dns_challenge.go
@@ -72,10 +72,10 @@ type dnsChallenge struct {
 }
 
 func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
-	log.Printf("[INFO][%s] acme: Trying to solve DNS-01", domain)
+	log.Infof("[%s] acme: Trying to solve DNS-01", domain)
 
 	if s.provider == nil {
-		return errors.New("No DNS Provider configured")
+		return errors.New("no DNS Provider configured")
 	}
 
 	// Generate the Key Authorization for the challenge
@@ -86,18 +86,18 @@ func (s *dnsChallenge) Solve(chlng challenge, domain string) error {
 
 	err = s.provider.Present(domain, chlng.Token, keyAuth)
 	if err != nil {
-		return fmt.Errorf("Error presenting token: %s", err)
+		return fmt.Errorf("error presenting token: %s", err)
 	}
 	defer func() {
 		err := s.provider.CleanUp(domain, chlng.Token, keyAuth)
 		if err != nil {
-			log.Printf("Error cleaning up %s: %v ", domain, err)
+			log.Warnf("Error cleaning up %s: %v ", domain, err)
 		}
 	}()
 
 	fqdn, value, _ := DNS01Record(domain, keyAuth)
 
-	log.Printf("[INFO][%s] Checking DNS record propagation using %+v", domain, RecursiveNameservers)
+	log.Infof("[%s] Checking DNS record propagation using %+v", domain, RecursiveNameservers)
 
 	var timeout, interval time.Duration
 	switch provider := s.provider.(type) {
diff --git a/acme/dns_challenge_manual.go b/acme/dns_challenge_manual.go
index cd4c3c8a..ca94fcac 100644
--- a/acme/dns_challenge_manual.go
+++ b/acme/dns_challenge_manual.go
@@ -30,9 +30,9 @@ func (*DNSProviderManual) Present(domain, token, keyAuth string) error {
 		return err
 	}
 
-	log.Printf("[INFO] acme: Please create the following TXT record in your %s zone:", authZone)
-	log.Printf("[INFO] acme: %s", dnsRecord)
-	log.Printf("[INFO] acme: Press 'Enter' when you are done")
+	log.Infof("acme: Please create the following TXT record in your %s zone:", authZone)
+	log.Infof("acme: %s", dnsRecord)
+	log.Infof("acme: Press 'Enter' when you are done")
 
 	reader := bufio.NewReader(os.Stdin)
 	_, _ = reader.ReadString('\n')
@@ -49,7 +49,7 @@ func (*DNSProviderManual) CleanUp(domain, token, keyAuth string) error {
 		return err
 	}
 
-	log.Printf("[INFO] acme: You can now remove this TXT record from your %s zone:", authZone)
-	log.Printf("[INFO] acme: %s", dnsRecord)
+	log.Infof("acme: You can now remove this TXT record from your %s zone:", authZone)
+	log.Infof("acme: %s", dnsRecord)
 	return nil
 }
diff --git a/acme/http.go b/acme/http.go
index 66caa728..e65a2382 100644
--- a/acme/http.go
+++ b/acme/http.go
@@ -80,7 +80,7 @@ func initCertPool() *x509.CertPool {
 // httpHead performs a HEAD request with a proper User-Agent string.
 // The response body (resp.Body) is already closed when this function returns.
 func httpHead(url string) (resp *http.Response, err error) {
-	req, err := http.NewRequest("HEAD", url, nil)
+	req, err := http.NewRequest(http.MethodHead, url, nil)
 	if err != nil {
 		return nil, fmt.Errorf("failed to head %q: %v", url, err)
 	}
@@ -98,7 +98,7 @@ func httpHead(url string) (resp *http.Response, err error) {
 // httpPost performs a POST request with a proper User-Agent string.
 // Callers should close resp.Body when done reading from it.
 func httpPost(url string, bodyType string, body io.Reader) (resp *http.Response, err error) {
-	req, err := http.NewRequest("POST", url, body)
+	req, err := http.NewRequest(http.MethodPost, url, body)
 	if err != nil {
 		return nil, fmt.Errorf("failed to post %q: %v", url, err)
 	}
@@ -111,7 +111,7 @@ func httpPost(url string, bodyType string, body io.Reader) (resp *http.Response,
 // httpGet performs a GET request with a proper User-Agent string.
 // Callers should close resp.Body when done reading from it.
 func httpGet(url string) (resp *http.Response, err error) {
-	req, err := http.NewRequest("GET", url, nil)
+	req, err := http.NewRequest(http.MethodGet, url, nil)
 	if err != nil {
 		return nil, fmt.Errorf("failed to get %q: %v", url, err)
 	}
diff --git a/acme/http_challenge.go b/acme/http_challenge.go
index 7659bfc5..77a8edd4 100644
--- a/acme/http_challenge.go
+++ b/acme/http_challenge.go
@@ -19,7 +19,7 @@ func HTTP01ChallengePath(token string) string {
 
 func (s *httpChallenge) Solve(chlng challenge, domain string) error {
 
-	log.Printf("[INFO][%s] acme: Trying to solve HTTP-01", domain)
+	log.Infof("[%s] acme: Trying to solve HTTP-01", domain)
 
 	// Generate the Key Authorization for the challenge
 	keyAuth, err := getKeyAuthorization(chlng.Token, s.jws.privKey)
@@ -34,7 +34,7 @@ func (s *httpChallenge) Solve(chlng challenge, domain string) error {
 	defer func() {
 		err := s.provider.CleanUp(domain, chlng.Token, keyAuth)
 		if err != nil {
-			log.Printf("[%s] error cleaning up: %v", domain, err)
+			log.Warnf("[%s] error cleaning up: %v", domain, err)
 		}
 	}()
 
diff --git a/acme/http_challenge_server.go b/acme/http_challenge_server.go
index 214a278f..319e2618 100644
--- a/acme/http_challenge_server.go
+++ b/acme/http_challenge_server.go
@@ -60,12 +60,12 @@ func (s *HTTPProviderServer) serve(domain, token, keyAuth string) {
 	// For validation it then writes the token the server returned with the challenge
 	mux := http.NewServeMux()
 	mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
-		if strings.HasPrefix(r.Host, domain) && r.Method == "GET" {
+		if strings.HasPrefix(r.Host, domain) && r.Method == http.MethodGet {
 			w.Header().Add("Content-Type", "text/plain")
 			w.Write([]byte(keyAuth))
-			log.Printf("[INFO][%s] Served key authentication", domain)
+			log.Infof("[%s] Served key authentication", domain)
 		} else {
-			log.Printf("[WARN] Received request for domain %s with method %s but the domain did not match any challenge. Please ensure your are passing the HOST header properly.", r.Host, r.Method)
+			log.Warnf("Received request for domain %s with method %s but the domain did not match any challenge. Please ensure your are passing the HOST header properly.", r.Host, r.Method)
 			w.Write([]byte("TEST"))
 		}
 	})
diff --git a/acme/tls_alpn_challenge.go b/acme/tls_alpn_challenge.go
index 397d0709..d8035199 100644
--- a/acme/tls_alpn_challenge.go
+++ b/acme/tls_alpn_challenge.go
@@ -23,7 +23,7 @@ type tlsALPNChallenge struct {
 
 // Solve manages the provider to validate and solve the challenge.
 func (t *tlsALPNChallenge) Solve(chlng challenge, domain string) error {
-	log.Printf("[INFO][%s] acme: Trying to solve TLS-ALPN-01", domain)
+	log.Infof("[%s] acme: Trying to solve TLS-ALPN-01", domain)
 
 	// Generate the Key Authorization for the challenge
 	keyAuth, err := getKeyAuthorization(chlng.Token, t.jws.privKey)
@@ -38,7 +38,7 @@ func (t *tlsALPNChallenge) Solve(chlng challenge, domain string) error {
 	defer func() {
 		err := t.provider.CleanUp(domain, chlng.Token, keyAuth)
 		if err != nil {
-			log.Printf("[%s] error cleaning up: %v", domain, err)
+			log.Warnf("[%s] error cleaning up: %v", domain, err)
 		}
 	}()
 
diff --git a/log/logger.go b/log/logger.go
index 291541c0..101a2c99 100644
--- a/log/logger.go
+++ b/log/logger.go
@@ -6,54 +6,44 @@ import (
 )
 
 // Logger is an optional custom logger.
-var Logger *log.Logger
+var Logger = log.New(os.Stdout, "", log.LstdFlags)
 
 // Fatal writes a log entry.
 // It uses Logger if not nil, otherwise it uses the default log.Logger.
 func Fatal(args ...interface{}) {
-	if Logger == nil {
-		Logger = log.New(os.Stderr, "", log.LstdFlags)
-	}
-
 	Logger.Fatal(args...)
 }
 
 // Fatalf writes a log entry.
 // It uses Logger if not nil, otherwise it uses the default log.Logger.
 func Fatalf(format string, args ...interface{}) {
-	if Logger == nil {
-		Logger = log.New(os.Stderr, "", log.LstdFlags)
-	}
-
 	Logger.Fatalf(format, args...)
 }
 
 // Print writes a log entry.
 // It uses Logger if not nil, otherwise it uses the default log.Logger.
 func Print(args ...interface{}) {
-	if Logger == nil {
-		Logger = log.New(os.Stdout, "", log.LstdFlags)
-	}
-
 	Logger.Print(args...)
 }
 
 // Println writes a log entry.
 // It uses Logger if not nil, otherwise it uses the default log.Logger.
 func Println(args ...interface{}) {
-	if Logger == nil {
-		Logger = log.New(os.Stdout, "", log.LstdFlags)
-	}
-
 	Logger.Println(args...)
 }
 
 // Printf writes a log entry.
 // It uses Logger if not nil, otherwise it uses the default log.Logger.
 func Printf(format string, args ...interface{}) {
-	if Logger == nil {
-		Logger = log.New(os.Stdout, "", log.LstdFlags)
-	}
-
 	Logger.Printf(format, args...)
 }
+
+// Warnf writes a log entry.
+func Warnf(format string, args ...interface{}) {
+	Printf("[WARN] "+format, args...)
+}
+
+// Infof writes a log entry.
+func Infof(format string, args ...interface{}) {
+	Printf("[INFO] "+format, args...)
+}
diff --git a/providers/dns/auroradns/auroradns.go b/providers/dns/auroradns/auroradns.go
index d7c09603..5c821507 100644
--- a/providers/dns/auroradns/auroradns.go
+++ b/providers/dns/auroradns/auroradns.go
@@ -51,8 +51,8 @@ func NewDNSProviderCredentials(baseURL string, userID string, key string) (*DNSP
 	}, nil
 }
 
-func (provider *DNSProvider) getZoneInformationByName(name string) (zones.ZoneRecord, error) {
-	zs, err := provider.client.GetZones()
+func (d *DNSProvider) getZoneInformationByName(name string) (zones.ZoneRecord, error) {
+	zs, err := d.client.GetZones()
 
 	if err != nil {
 		return zones.ZoneRecord{}, err
@@ -68,7 +68,7 @@ func (provider *DNSProvider) getZoneInformationByName(name string) (zones.ZoneRe
 }
 
 // Present creates a record with a secret
-func (provider *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
 
 	authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
@@ -87,7 +87,7 @@ func (provider *DNSProvider) Present(domain, token, keyAuth string) error {
 
 	authZone = acme.UnFqdn(authZone)
 
-	zoneRecord, err := provider.getZoneInformationByName(authZone)
+	zoneRecord, err := d.getZoneInformationByName(authZone)
 	if err != nil {
 		return fmt.Errorf("could not create record: %v", err)
 	}
@@ -100,25 +100,25 @@ func (provider *DNSProvider) Present(domain, token, keyAuth string) error {
 			TTL:        300,
 		}
 
-	respData, err := provider.client.CreateRecord(zoneRecord.ID, reqData)
+	respData, err := d.client.CreateRecord(zoneRecord.ID, reqData)
 	if err != nil {
 		return fmt.Errorf("could not create record: %v", err)
 	}
 
-	provider.recordIDsMu.Lock()
-	provider.recordIDs[fqdn] = respData.ID
-	provider.recordIDsMu.Unlock()
+	d.recordIDsMu.Lock()
+	d.recordIDs[fqdn] = respData.ID
+	d.recordIDsMu.Unlock()
 
 	return nil
 }
 
 // CleanUp removes a given record that was generated by Present
-func (provider *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
 
-	provider.recordIDsMu.Lock()
-	recordID, ok := provider.recordIDs[fqdn]
-	provider.recordIDsMu.Unlock()
+	d.recordIDsMu.Lock()
+	recordID, ok := d.recordIDs[fqdn]
+	d.recordIDsMu.Unlock()
 
 	if !ok {
 		return fmt.Errorf("unknown recordID for %q", fqdn)
@@ -131,19 +131,19 @@ func (provider *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 
 	authZone = acme.UnFqdn(authZone)
 
-	zoneRecord, err := provider.getZoneInformationByName(authZone)
+	zoneRecord, err := d.getZoneInformationByName(authZone)
 	if err != nil {
 		return err
 	}
 
-	_, err = provider.client.RemoveRecord(zoneRecord.ID, recordID)
+	_, err = d.client.RemoveRecord(zoneRecord.ID, recordID)
 	if err != nil {
 		return err
 	}
 
-	provider.recordIDsMu.Lock()
-	delete(provider.recordIDs, fqdn)
-	provider.recordIDsMu.Unlock()
+	d.recordIDsMu.Lock()
+	delete(d.recordIDs, fqdn)
+	d.recordIDsMu.Unlock()
 
 	return nil
 }
diff --git a/providers/dns/azure/azure.go b/providers/dns/azure/azure.go
index abd342eb..bbf2c7fb 100644
--- a/providers/dns/azure/azure.go
+++ b/providers/dns/azure/azure.go
@@ -67,20 +67,20 @@ func NewDNSProviderCredentials(clientID, clientSecret, subscriptionID, tenantID,
 
 // Timeout returns the timeout and interval to use when checking for DNS
 // propagation. Adjusting here to cope with spikes in propagation times.
-func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
+func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
 	return 120 * time.Second, 2 * time.Second
 }
 
 // Present creates a TXT record to fulfil the dns-01 challenge
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
-	zone, err := c.getHostedZoneID(fqdn)
+	zone, err := d.getHostedZoneID(fqdn)
 	if err != nil {
 		return err
 	}
 
-	rsc := dns.NewRecordSetsClient(c.subscriptionID)
-	spt, err := c.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
+	rsc := dns.NewRecordSetsClient(d.subscriptionID)
+	spt, err := d.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
 	if err != nil {
 		return err
 	}
@@ -96,7 +96,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 		},
 	}
 
-	_, err = rsc.CreateOrUpdate(c.context, c.resourceGroup, zone, relative, dns.TXT, rec, "", "")
+	_, err = rsc.CreateOrUpdate(d.context, d.resourceGroup, zone, relative, dns.TXT, rec, "", "")
 	return err
 }
 
@@ -106,44 +106,44 @@ func toRelativeRecord(domain, zone string) string {
 }
 
 // CleanUp removes the TXT record matching the specified parameters
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
 
-	zone, err := c.getHostedZoneID(fqdn)
+	zone, err := d.getHostedZoneID(fqdn)
 	if err != nil {
 		return err
 	}
 
 	relative := toRelativeRecord(fqdn, acme.ToFqdn(zone))
-	rsc := dns.NewRecordSetsClient(c.subscriptionID)
-	spt, err := c.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
+	rsc := dns.NewRecordSetsClient(d.subscriptionID)
+	spt, err := d.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
 	if err != nil {
 		return err
 	}
 
 	rsc.Authorizer = autorest.NewBearerAuthorizer(spt)
 
-	_, err = rsc.Delete(c.context, c.resourceGroup, zone, relative, dns.TXT, "")
+	_, err = rsc.Delete(d.context, d.resourceGroup, zone, relative, dns.TXT, "")
 	return err
 }
 
 // Checks that azure has a zone for this domain name.
-func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
+func (d *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
 	authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
 	if err != nil {
 		return "", err
 	}
 
 	// Now we want to to Azure and get the zone.
-	spt, err := c.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
+	spt, err := d.newServicePrincipalTokenFromCredentials(azure.PublicCloud.ResourceManagerEndpoint)
 	if err != nil {
 		return "", err
 	}
 
-	dc := dns.NewZonesClient(c.subscriptionID)
+	dc := dns.NewZonesClient(d.subscriptionID)
 	dc.Authorizer = autorest.NewBearerAuthorizer(spt)
 
-	zone, err := dc.Get(c.context, c.resourceGroup, acme.UnFqdn(authZone))
+	zone, err := dc.Get(d.context, d.resourceGroup, acme.UnFqdn(authZone))
 	if err != nil {
 		return "", err
 	}
@@ -154,10 +154,10 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
 
 // NewServicePrincipalTokenFromCredentials creates a new ServicePrincipalToken using values of the
 // passed credentials map.
-func (c *DNSProvider) newServicePrincipalTokenFromCredentials(scope string) (*adal.ServicePrincipalToken, error) {
-	oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, c.tenantID)
+func (d *DNSProvider) newServicePrincipalTokenFromCredentials(scope string) (*adal.ServicePrincipalToken, error) {
+	oauthConfig, err := adal.NewOAuthConfig(azure.PublicCloud.ActiveDirectoryEndpoint, d.tenantID)
 	if err != nil {
 		return nil, err
 	}
-	return adal.NewServicePrincipalToken(*oauthConfig, c.clientID, c.clientSecret, scope)
+	return adal.NewServicePrincipalToken(*oauthConfig, d.clientID, d.clientSecret, scope)
 }
diff --git a/providers/dns/bluecat/bluecat.go b/providers/dns/bluecat/bluecat.go
index 83a502ca..d88d73b1 100644
--- a/providers/dns/bluecat/bluecat.go
+++ b/providers/dns/bluecat/bluecat.go
@@ -39,7 +39,7 @@ type DNSProvider struct {
 	configName string
 	dnsView    string
 	token      string
-	httpClient *http.Client
+	client     *http.Client
 }
 
 // NewDNSProvider returns a DNSProvider instance configured for Bluecat DNS.
@@ -85,7 +85,7 @@ func NewDNSProviderCredentials(server, userName, password, configName, dnsView s
 		password:   password,
 		configName: configName,
 		dnsView:    dnsView,
-		httpClient: client,
+		client:     client,
 	}, nil
 }
 
@@ -114,7 +114,7 @@ func (d *DNSProvider) sendRequest(method, resource string, payload interface{},
 		q.Add(argName, argVal)
 	}
 	req.URL.RawQuery = q.Encode()
-	resp, err := d.httpClient.Do(req)
+	resp, err := d.client.Do(req)
 	if err != nil {
 		return nil, err
 	}
@@ -137,13 +137,16 @@ func (d *DNSProvider) login() error {
 		"password": d.password,
 	}
 
-	resp, err := d.sendRequest("GET", "login", nil, queryArgs)
+	resp, err := d.sendRequest(http.MethodGet, "login", nil, queryArgs)
 	if err != nil {
 		return err
 	}
 	defer resp.Body.Close()
 
-	authBytes, _ := ioutil.ReadAll(resp.Body)
+	authBytes, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return err
+	}
 	authResp := string(authBytes)
 
 	if strings.Contains(authResp, "Authentication Error") {
@@ -164,7 +167,7 @@ func (d *DNSProvider) logout() error {
 		return nil
 	}
 
-	resp, err := d.sendRequest("GET", "logout", nil, nil)
+	resp, err := d.sendRequest(http.MethodGet, "logout", nil, nil)
 	if err != nil {
 		return err
 	}
@@ -174,7 +177,10 @@ func (d *DNSProvider) logout() error {
 		return fmt.Errorf("Bluecat API request failed to delete session with HTTP status code %d", resp.StatusCode)
 	}
 
-	authBytes, _ := ioutil.ReadAll(resp.Body)
+	authBytes, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return err
+	}
 	authResp := string(authBytes)
 
 	if !strings.Contains(authResp, "successfully") {
@@ -195,7 +201,7 @@ func (d *DNSProvider) lookupConfID() (uint, error) {
 		"type":     configType,
 	}
 
-	resp, err := d.sendRequest("GET", "getEntityByName", nil, queryArgs)
+	resp, err := d.sendRequest(http.MethodGet, "getEntityByName", nil, queryArgs)
 	if err != nil {
 		return 0, err
 	}
@@ -222,7 +228,7 @@ func (d *DNSProvider) lookupViewID(viewName string) (uint, error) {
 		"type":     viewType,
 	}
 
-	resp, err := d.sendRequest("GET", "getEntityByName", nil, queryArgs)
+	resp, err := d.sendRequest(http.MethodGet, "getEntityByName", nil, queryArgs)
 	if err != nil {
 		return 0, err
 	}
@@ -271,7 +277,7 @@ func (d *DNSProvider) getZone(parentID uint, name string) (uint, error) {
 		"type":     zoneType,
 	}
 
-	resp, err := d.sendRequest("GET", "getEntityByName", nil, queryArgs)
+	resp, err := d.sendRequest(http.MethodGet, "getEntityByName", nil, queryArgs)
 	// Return an empty zone if the named zone doesn't exist
 	if resp != nil && resp.StatusCode == 404 {
 		return 0, fmt.Errorf("Bluecat API could not find zone named %s", name)
@@ -321,8 +327,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 		Properties: fmt.Sprintf("ttl=%d|absoluteName=%s|txt=%s|", ttl, fqdn, value),
 	}
 
-	resp, err := d.sendRequest("POST", "addEntity", body, queryArgs)
-
+	resp, err := d.sendRequest(http.MethodPost, "addEntity", body, queryArgs)
 	if err != nil {
 		return err
 	}
@@ -350,8 +355,7 @@ func (d *DNSProvider) deploy(entityID uint) error {
 		"entityId": strconv.FormatUint(uint64(entityID), 10),
 	}
 
-	resp, err := d.sendRequest("POST", "quickDeploy", nil, queryArgs)
-
+	resp, err := d.sendRequest(http.MethodPost, "quickDeploy", nil, queryArgs)
 	if err != nil {
 		return err
 	}
@@ -385,7 +389,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 		"type":     txtType,
 	}
 
-	resp, err := d.sendRequest("GET", "getEntityByName", nil, queryArgs)
+	resp, err := d.sendRequest(http.MethodGet, "getEntityByName", nil, queryArgs)
 	if err != nil {
 		return err
 	}
@@ -400,7 +404,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 		"objectId": strconv.FormatUint(uint64(txtRec.ID), 10),
 	}
 
-	resp, err = d.sendRequest("DELETE", "delete", nil, queryArgs)
+	resp, err = d.sendRequest(http.MethodDelete, http.MethodDelete, nil, queryArgs)
 	if err != nil {
 		return err
 	}
diff --git a/providers/dns/cloudflare/cloudflare.go b/providers/dns/cloudflare/cloudflare.go
index 85bbe498..7d8979ef 100644
--- a/providers/dns/cloudflare/cloudflare.go
+++ b/providers/dns/cloudflare/cloudflare.go
@@ -24,6 +24,7 @@ const CloudFlareAPIURL = "https://api.cloudflare.com/client/v4"
 type DNSProvider struct {
 	authEmail string
 	authKey   string
+	client    *http.Client
 }
 
 // NewDNSProvider returns a DNSProvider instance configured for cloudflare.
@@ -48,19 +49,20 @@ func NewDNSProviderCredentials(email, key string) (*DNSProvider, error) {
 	return &DNSProvider{
 		authEmail: email,
 		authKey:   key,
+		client:    &http.Client{Timeout: 30 * time.Second},
 	}, nil
 }
 
 // Timeout returns the timeout and interval to use when checking for DNS
 // propagation. Adjusting here to cope with spikes in propagation times.
-func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
+func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
 	return 120 * time.Second, 2 * time.Second
 }
 
 // Present creates a TXT record to fulfil the dns-01 challenge
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-	zoneID, err := c.getHostedZoneID(fqdn)
+	zoneID, err := d.getHostedZoneID(fqdn)
 	if err != nil {
 		return err
 	}
@@ -77,24 +79,24 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 		return err
 	}
 
-	_, err = c.makeRequest("POST", fmt.Sprintf("/zones/%s/dns_records", zoneID), bytes.NewReader(body))
+	_, err = d.doRequest(http.MethodPost, fmt.Sprintf("/zones/%s/dns_records", zoneID), bytes.NewReader(body))
 	return err
 }
 
 // CleanUp removes the TXT record matching the specified parameters
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
 
-	record, err := c.findTxtRecord(fqdn)
+	record, err := d.findTxtRecord(fqdn)
 	if err != nil {
 		return err
 	}
 
-	_, err = c.makeRequest("DELETE", fmt.Sprintf("/zones/%s/dns_records/%s", record.ZoneID, record.ID), nil)
+	_, err = d.doRequest(http.MethodDelete, fmt.Sprintf("/zones/%s/dns_records/%s", record.ZoneID, record.ID), nil)
 	return err
 }
 
-func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
+func (d *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
 	// HostedZone represents a CloudFlare DNS zone
 	type HostedZone struct {
 		ID   string `json:"id"`
@@ -106,7 +108,7 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
 		return "", err
 	}
 
-	result, err := c.makeRequest("GET", "/zones?name="+acme.UnFqdn(authZone), nil)
+	result, err := d.doRequest(http.MethodGet, "/zones?name="+acme.UnFqdn(authZone), nil)
 	if err != nil {
 		return "", err
 	}
@@ -124,14 +126,14 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
 	return hostedZone[0].ID, nil
 }
 
-func (c *DNSProvider) findTxtRecord(fqdn string) (*cloudFlareRecord, error) {
-	zoneID, err := c.getHostedZoneID(fqdn)
+func (d *DNSProvider) findTxtRecord(fqdn string) (*cloudFlareRecord, error) {
+	zoneID, err := d.getHostedZoneID(fqdn)
 	if err != nil {
 		return nil, err
 	}
 
-	result, err := c.makeRequest(
-		"GET",
+	result, err := d.doRequest(
+		http.MethodGet,
 		fmt.Sprintf("/zones/%s/dns_records?per_page=1000&type=TXT&name=%s", zoneID, acme.UnFqdn(fqdn)),
 		nil,
 	)
@@ -154,31 +156,16 @@ func (c *DNSProvider) findTxtRecord(fqdn string) (*cloudFlareRecord, error) {
 	return nil, fmt.Errorf("no existing record found for %s", fqdn)
 }
 
-func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
-	// APIError contains error details for failed requests
-	type APIError struct {
-		Code       int        `json:"code,omitempty"`
-		Message    string     `json:"message,omitempty"`
-		ErrorChain []APIError `json:"error_chain,omitempty"`
-	}
-
-	// APIResponse represents a response from CloudFlare API
-	type APIResponse struct {
-		Success bool            `json:"success"`
-		Errors  []*APIError     `json:"errors"`
-		Result  json.RawMessage `json:"result"`
-	}
-
+func (d *DNSProvider) doRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
 	req, err := http.NewRequest(method, fmt.Sprintf("%s%s", CloudFlareAPIURL, uri), body)
 	if err != nil {
 		return nil, err
 	}
 
-	req.Header.Set("X-Auth-Email", c.authEmail)
-	req.Header.Set("X-Auth-Key", c.authKey)
+	req.Header.Set("X-Auth-Email", d.authEmail)
+	req.Header.Set("X-Auth-Key", d.authKey)
 
-	client := http.Client{Timeout: 30 * time.Second}
-	resp, err := client.Do(req)
+	resp, err := d.client.Do(req)
 	if err != nil {
 		return nil, fmt.Errorf("error querying Cloudflare API -> %v", err)
 	}
@@ -212,6 +199,20 @@ func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawM
 	return r.Result, nil
 }
 
+// APIError contains error details for failed requests
+type APIError struct {
+	Code       int        `json:"code,omitempty"`
+	Message    string     `json:"message,omitempty"`
+	ErrorChain []APIError `json:"error_chain,omitempty"`
+}
+
+// APIResponse represents a response from CloudFlare API
+type APIResponse struct {
+	Success bool            `json:"success"`
+	Errors  []*APIError     `json:"errors"`
+	Result  json.RawMessage `json:"result"`
+}
+
 // cloudFlareRecord represents a CloudFlare DNS record
 type cloudFlareRecord struct {
 	Name    string `json:"name"`
diff --git a/providers/dns/cloudxns/cloudxns.go b/providers/dns/cloudxns/cloudxns.go
index 26655552..ae819f12 100644
--- a/providers/dns/cloudxns/cloudxns.go
+++ b/providers/dns/cloudxns/cloudxns.go
@@ -50,33 +50,33 @@ func NewDNSProviderCredentials(apiKey, secretKey string) (*DNSProvider, error) {
 }
 
 // Present creates a TXT record to fulfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-	zoneID, err := c.getHostedZoneID(fqdn)
+	zoneID, err := d.getHostedZoneID(fqdn)
 	if err != nil {
 		return err
 	}
 
-	return c.addTxtRecord(zoneID, fqdn, value, ttl)
+	return d.addTxtRecord(zoneID, fqdn, value, ttl)
 }
 
 // CleanUp removes the TXT record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-	zoneID, err := c.getHostedZoneID(fqdn)
+	zoneID, err := d.getHostedZoneID(fqdn)
 	if err != nil {
 		return err
 	}
 
-	recordID, err := c.findTxtRecord(zoneID, fqdn)
+	recordID, err := d.findTxtRecord(zoneID, fqdn)
 	if err != nil {
 		return err
 	}
 
-	return c.delTxtRecord(recordID, zoneID)
+	return d.delTxtRecord(recordID, zoneID)
 }
 
-func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
+func (d *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
 	type Data struct {
 		ID     string `json:"id"`
 		Domain string `json:"domain"`
@@ -87,7 +87,7 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
 		return "", err
 	}
 
-	result, err := c.makeRequest("GET", "domain", nil)
+	result, err := d.makeRequest(http.MethodGet, "domain", nil)
 	if err != nil {
 		return "", err
 	}
@@ -107,8 +107,8 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (string, error) {
 	return "", fmt.Errorf("zone %s not found in cloudxns for domain %s", authZone, fqdn)
 }
 
-func (c *DNSProvider) findTxtRecord(zoneID, fqdn string) (string, error) {
-	result, err := c.makeRequest("GET", fmt.Sprintf("record/%s?host_id=0&offset=0&row_num=2000", zoneID), nil)
+func (d *DNSProvider) findTxtRecord(zoneID, fqdn string) (string, error) {
+	result, err := d.makeRequest(http.MethodGet, fmt.Sprintf("record/%s?host_id=0&offset=0&row_num=2000", zoneID), nil)
 	if err != nil {
 		return "", err
 	}
@@ -128,7 +128,7 @@ func (c *DNSProvider) findTxtRecord(zoneID, fqdn string) (string, error) {
 	return "", fmt.Errorf("no existing record found for %s", fqdn)
 }
 
-func (c *DNSProvider) addTxtRecord(zoneID, fqdn, value string, ttl int) error {
+func (d *DNSProvider) addTxtRecord(zoneID, fqdn, value string, ttl int) error {
 	id, err := strconv.Atoi(zoneID)
 	if err != nil {
 		return err
@@ -148,21 +148,21 @@ func (c *DNSProvider) addTxtRecord(zoneID, fqdn, value string, ttl int) error {
 		return err
 	}
 
-	_, err = c.makeRequest("POST", "record", body)
+	_, err = d.makeRequest(http.MethodPost, "record", body)
 	return err
 }
 
-func (c *DNSProvider) delTxtRecord(recordID, zoneID string) error {
-	_, err := c.makeRequest("DELETE", fmt.Sprintf("record/%s/%s", recordID, zoneID), nil)
+func (d *DNSProvider) delTxtRecord(recordID, zoneID string) error {
+	_, err := d.makeRequest(http.MethodDelete, fmt.Sprintf("record/%s/%s", recordID, zoneID), nil)
 	return err
 }
 
-func (c *DNSProvider) hmac(url, date, body string) string {
-	sum := md5.Sum([]byte(c.apiKey + url + body + date + c.secretKey))
+func (d *DNSProvider) hmac(url, date, body string) string {
+	sum := md5.Sum([]byte(d.apiKey + url + body + date + d.secretKey))
 	return hex.EncodeToString(sum[:])
 }
 
-func (c *DNSProvider) makeRequest(method, uri string, body []byte) (json.RawMessage, error) {
+func (d *DNSProvider) makeRequest(method, uri string, body []byte) (json.RawMessage, error) {
 	type APIResponse struct {
 		Code    int             `json:"code"`
 		Message string          `json:"message"`
@@ -177,9 +177,9 @@ func (c *DNSProvider) makeRequest(method, uri string, body []byte) (json.RawMess
 
 	requestDate := time.Now().Format(time.RFC1123Z)
 
-	req.Header.Set("API-KEY", c.apiKey)
+	req.Header.Set("API-KEY", d.apiKey)
 	req.Header.Set("API-REQUEST-DATE", requestDate)
-	req.Header.Set("API-HMAC", c.hmac(url, requestDate, string(body)))
+	req.Header.Set("API-HMAC", d.hmac(url, requestDate, string(body)))
 	req.Header.Set("API-FORMAT", "json")
 
 	resp, err := acme.HTTPClient.Do(req)
diff --git a/providers/dns/digitalocean/digitalocean.go b/providers/dns/digitalocean/digitalocean.go
index 9abb97d8..e4247046 100644
--- a/providers/dns/digitalocean/digitalocean.go
+++ b/providers/dns/digitalocean/digitalocean.go
@@ -20,12 +20,7 @@ type DNSProvider struct {
 	apiAuthToken string
 	recordIDs    map[string]int
 	recordIDsMu  sync.Mutex
-}
-
-// Timeout returns the timeout and interval to use when checking for DNS
-// propagation. Adjusting here to cope with spikes in propagation times.
-func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
-	return 60 * time.Second, 5 * time.Second
+	client       *http.Client
 }
 
 // NewDNSProvider returns a DNSProvider instance configured for Digital
@@ -49,9 +44,16 @@ func NewDNSProviderCredentials(apiAuthToken string) (*DNSProvider, error) {
 	return &DNSProvider{
 		apiAuthToken: apiAuthToken,
 		recordIDs:    make(map[string]int),
+		client:       &http.Client{Timeout: 30 * time.Second},
 	}, nil
 }
 
+// Timeout returns the timeout and interval to use when checking for DNS
+// propagation. Adjusting here to cope with spikes in propagation times.
+func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
+	return 60 * time.Second, 5 * time.Second
+}
+
 // Present creates a TXT record using the specified parameters
 func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
@@ -70,15 +72,14 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 		return err
 	}
 
-	req, err := http.NewRequest("POST", reqURL, bytes.NewReader(body))
+	req, err := http.NewRequest(http.MethodPost, reqURL, bytes.NewReader(body))
 	if err != nil {
 		return err
 	}
 	req.Header.Set("Content-Type", "application/json")
 	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", d.apiAuthToken))
 
-	client := http.Client{Timeout: 30 * time.Second}
-	resp, err := client.Do(req)
+	resp, err := d.client.Do(req)
 	if err != nil {
 		return err
 	}
@@ -123,15 +124,15 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	authZone = acme.UnFqdn(authZone)
 
 	reqURL := fmt.Sprintf("%s/v2/domains/%s/records/%d", digitalOceanBaseURL, authZone, recordID)
-	req, err := http.NewRequest("DELETE", reqURL, nil)
+	req, err := http.NewRequest(http.MethodDelete, reqURL, nil)
 	if err != nil {
 		return err
 	}
+
 	req.Header.Set("Content-Type", "application/json")
 	req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", d.apiAuthToken))
 
-	client := http.Client{Timeout: 30 * time.Second}
-	resp, err := client.Do(req)
+	resp, err := d.client.Do(req)
 	if err != nil {
 		return err
 	}
diff --git a/providers/dns/dns_providers.go b/providers/dns/dns_providers.go
index d0002861..0f54c27f 100644
--- a/providers/dns/dns_providers.go
+++ b/providers/dns/dns_providers.go
@@ -39,75 +39,72 @@ import (
 
 // NewDNSChallengeProviderByName Factory for DNS providers
 func NewDNSChallengeProviderByName(name string) (acme.ChallengeProvider, error) {
-	var err error
-	var provider acme.ChallengeProvider
 	switch name {
 	case "azure":
-		provider, err = azure.NewDNSProvider()
+		return azure.NewDNSProvider()
 	case "auroradns":
-		provider, err = auroradns.NewDNSProvider()
+		return auroradns.NewDNSProvider()
 	case "bluecat":
-		provider, err = bluecat.NewDNSProvider()
+		return bluecat.NewDNSProvider()
 	case "cloudflare":
-		provider, err = cloudflare.NewDNSProvider()
+		return cloudflare.NewDNSProvider()
 	case "cloudxns":
-		provider, err = cloudxns.NewDNSProvider()
+		return cloudxns.NewDNSProvider()
 	case "digitalocean":
-		provider, err = digitalocean.NewDNSProvider()
+		return digitalocean.NewDNSProvider()
 	case "dnsimple":
-		provider, err = dnsimple.NewDNSProvider()
+		return dnsimple.NewDNSProvider()
 	case "dnsmadeeasy":
-		provider, err = dnsmadeeasy.NewDNSProvider()
+		return dnsmadeeasy.NewDNSProvider()
 	case "dnspod":
-		provider, err = dnspod.NewDNSProvider()
+		return dnspod.NewDNSProvider()
 	case "duckdns":
-		provider, err = duckdns.NewDNSProvider()
+		return duckdns.NewDNSProvider()
 	case "dyn":
-		provider, err = dyn.NewDNSProvider()
+		return dyn.NewDNSProvider()
 	case "fastdns":
-		provider, err = fastdns.NewDNSProvider()
+		return fastdns.NewDNSProvider()
 	case "exoscale":
-		provider, err = exoscale.NewDNSProvider()
+		return exoscale.NewDNSProvider()
 	case "gandi":
-		provider, err = gandi.NewDNSProvider()
+		return gandi.NewDNSProvider()
 	case "gandiv5":
-		provider, err = gandiv5.NewDNSProvider()
+		return gandiv5.NewDNSProvider()
 	case "glesys":
-		provider, err = glesys.NewDNSProvider()
+		return glesys.NewDNSProvider()
 	case "gcloud":
-		provider, err = gcloud.NewDNSProvider()
+		return gcloud.NewDNSProvider()
 	case "godaddy":
-		provider, err = godaddy.NewDNSProvider()
+		return godaddy.NewDNSProvider()
 	case "lightsail":
-		provider, err = lightsail.NewDNSProvider()
+		return lightsail.NewDNSProvider()
 	case "linode":
-		provider, err = linode.NewDNSProvider()
+		return linode.NewDNSProvider()
 	case "manual":
-		provider, err = acme.NewDNSProviderManual()
+		return acme.NewDNSProviderManual()
 	case "namecheap":
-		provider, err = namecheap.NewDNSProvider()
+		return namecheap.NewDNSProvider()
 	case "namedotcom":
-		provider, err = namedotcom.NewDNSProvider()
+		return namedotcom.NewDNSProvider()
 	case "rackspace":
-		provider, err = rackspace.NewDNSProvider()
+		return rackspace.NewDNSProvider()
 	case "route53":
-		provider, err = route53.NewDNSProvider()
+		return route53.NewDNSProvider()
 	case "rfc2136":
-		provider, err = rfc2136.NewDNSProvider()
+		return rfc2136.NewDNSProvider()
 	case "vultr":
-		provider, err = vultr.NewDNSProvider()
+		return vultr.NewDNSProvider()
 	case "ovh":
-		provider, err = ovh.NewDNSProvider()
+		return ovh.NewDNSProvider()
 	case "pdns":
-		provider, err = pdns.NewDNSProvider()
+		return pdns.NewDNSProvider()
 	case "ns1":
-		provider, err = ns1.NewDNSProvider()
+		return ns1.NewDNSProvider()
 	case "otc":
-		provider, err = otc.NewDNSProvider()
+		return otc.NewDNSProvider()
 	case "exec":
-		provider, err = exec.NewDNSProvider()
+		return exec.NewDNSProvider()
 	default:
-		err = fmt.Errorf("unrecognised DNS provider: %s", name)
+		return nil, fmt.Errorf("unrecognised DNS provider: %s", name)
 	}
-	return provider, err
 }
diff --git a/providers/dns/dnsimple/dnsimple.go b/providers/dns/dnsimple/dnsimple.go
index 30c7fc2f..a9f8424a 100644
--- a/providers/dns/dnsimple/dnsimple.go
+++ b/providers/dns/dnsimple/dnsimple.go
@@ -46,22 +46,22 @@ func NewDNSProviderCredentials(accessToken, baseURL string) (*DNSProvider, error
 }
 
 // Present creates a TXT record to fulfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
 
-	zoneName, err := c.getHostedZone(domain)
+	zoneName, err := d.getHostedZone(domain)
 
 	if err != nil {
 		return err
 	}
 
-	accountID, err := c.getAccountID()
+	accountID, err := d.getAccountID()
 	if err != nil {
 		return err
 	}
 
-	recordAttributes := c.newTxtRecord(zoneName, fqdn, value, ttl)
-	_, err = c.client.Zones.CreateRecord(accountID, zoneName, *recordAttributes)
+	recordAttributes := d.newTxtRecord(zoneName, fqdn, value, ttl)
+	_, err = d.client.Zones.CreateRecord(accountID, zoneName, *recordAttributes)
 	if err != nil {
 		return fmt.Errorf("DNSimple API call failed: %v", err)
 	}
@@ -70,21 +70,21 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 }
 
 // CleanUp removes the TXT record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
 
-	records, err := c.findTxtRecords(domain, fqdn)
+	records, err := d.findTxtRecords(domain, fqdn)
 	if err != nil {
 		return err
 	}
 
-	accountID, err := c.getAccountID()
+	accountID, err := d.getAccountID()
 	if err != nil {
 		return err
 	}
 
 	for _, rec := range records {
-		_, err := c.client.Zones.DeleteRecord(accountID, rec.ZoneID, rec.ID)
+		_, err := d.client.Zones.DeleteRecord(accountID, rec.ZoneID, rec.ID)
 		if err != nil {
 			return err
 		}
@@ -93,20 +93,20 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	return nil
 }
 
-func (c *DNSProvider) getHostedZone(domain string) (string, error) {
+func (d *DNSProvider) getHostedZone(domain string) (string, error) {
 	authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
 	if err != nil {
 		return "", err
 	}
 
-	accountID, err := c.getAccountID()
+	accountID, err := d.getAccountID()
 	if err != nil {
 		return "", err
 	}
 
 	zoneName := acme.UnFqdn(authZone)
 
-	zones, err := c.client.Zones.ListZones(accountID, &dnsimple.ZoneListOptions{NameLike: zoneName})
+	zones, err := d.client.Zones.ListZones(accountID, &dnsimple.ZoneListOptions{NameLike: zoneName})
 	if err != nil {
 		return "", fmt.Errorf("DNSimple API call failed: %v", err)
 	}
@@ -125,20 +125,20 @@ func (c *DNSProvider) getHostedZone(domain string) (string, error) {
 	return hostedZone.Name, nil
 }
 
-func (c *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnsimple.ZoneRecord, error) {
-	zoneName, err := c.getHostedZone(domain)
+func (d *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnsimple.ZoneRecord, error) {
+	zoneName, err := d.getHostedZone(domain)
 	if err != nil {
 		return nil, err
 	}
 
-	accountID, err := c.getAccountID()
+	accountID, err := d.getAccountID()
 	if err != nil {
 		return nil, err
 	}
 
-	recordName := c.extractRecordName(fqdn, zoneName)
+	recordName := d.extractRecordName(fqdn, zoneName)
 
-	result, err := c.client.Zones.ListRecords(accountID, zoneName, &dnsimple.ZoneRecordListOptions{Name: recordName, Type: "TXT", ListOptions: dnsimple.ListOptions{}})
+	result, err := d.client.Zones.ListRecords(accountID, zoneName, &dnsimple.ZoneRecordListOptions{Name: recordName, Type: "TXT", ListOptions: dnsimple.ListOptions{}})
 	if err != nil {
 		return []dnsimple.ZoneRecord{}, fmt.Errorf("DNSimple API call has failed: %v", err)
 	}
@@ -146,8 +146,8 @@ func (c *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnsimple.ZoneRecord
 	return result.Data, nil
 }
 
-func (c *DNSProvider) newTxtRecord(zoneName, fqdn, value string, ttl int) *dnsimple.ZoneRecord {
-	name := c.extractRecordName(fqdn, zoneName)
+func (d *DNSProvider) newTxtRecord(zoneName, fqdn, value string, ttl int) *dnsimple.ZoneRecord {
+	name := d.extractRecordName(fqdn, zoneName)
 
 	return &dnsimple.ZoneRecord{
 		Type:    "TXT",
@@ -157,7 +157,7 @@ func (c *DNSProvider) newTxtRecord(zoneName, fqdn, value string, ttl int) *dnsim
 	}
 }
 
-func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
+func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
 	name := acme.UnFqdn(fqdn)
 	if idx := strings.Index(name, "."+domain); idx != -1 {
 		return name[:idx]
@@ -165,8 +165,8 @@ func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
 	return name
 }
 
-func (c *DNSProvider) getAccountID() (string, error) {
-	whoamiResponse, err := c.client.Identity.Whoami()
+func (d *DNSProvider) getAccountID() (string, error) {
+	whoamiResponse, err := d.client.Identity.Whoami()
 	if err != nil {
 		return "", err
 	}
diff --git a/providers/dns/dnsmadeeasy/dnsmadeeasy.go b/providers/dns/dnsmadeeasy/dnsmadeeasy.go
index 2083cdc5..9f7f31a9 100644
--- a/providers/dns/dnsmadeeasy/dnsmadeeasy.go
+++ b/providers/dns/dnsmadeeasy/dnsmadeeasy.go
@@ -24,6 +24,7 @@ type DNSProvider struct {
 	baseURL   string
 	apiKey    string
 	apiSecret string
+	client    *http.Client
 }
 
 // Domain holds the DNSMadeEasy API representation of a Domain
@@ -68,10 +69,19 @@ func NewDNSProviderCredentials(baseURL, apiKey, apiSecret string) (*DNSProvider,
 		return nil, fmt.Errorf("DNS Made Easy credentials missing")
 	}
 
+	transport := &http.Transport{
+		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+	}
+	client := &http.Client{
+		Transport: transport,
+		Timeout:   10 * time.Second,
+	}
+
 	return &DNSProvider{
 		baseURL:   baseURL,
 		apiKey:    apiKey,
 		apiSecret: apiSecret,
+		client:    client,
 	}, nil
 }
 
@@ -135,7 +145,7 @@ func (d *DNSProvider) getDomain(authZone string) (*Domain, error) {
 	domainName := authZone[0 : len(authZone)-1]
 	resource := fmt.Sprintf("%s%s", "/dns/managed/name?domainname=", domainName)
 
-	resp, err := d.sendRequest("GET", resource, nil)
+	resp, err := d.sendRequest(http.MethodGet, resource, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -153,7 +163,7 @@ func (d *DNSProvider) getDomain(authZone string) (*Domain, error) {
 func (d *DNSProvider) getRecords(domain *Domain, recordName, recordType string) (*[]Record, error) {
 	resource := fmt.Sprintf("%s/%d/%s%s%s%s", "/dns/managed", domain.ID, "records?recordName=", recordName, "&type=", recordType)
 
-	resp, err := d.sendRequest("GET", resource, nil)
+	resp, err := d.sendRequest(http.MethodGet, resource, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -175,7 +185,7 @@ func (d *DNSProvider) getRecords(domain *Domain, recordName, recordType string)
 func (d *DNSProvider) createRecord(domain *Domain, record *Record) error {
 	url := fmt.Sprintf("%s/%d/%s", "/dns/managed", domain.ID, "records")
 
-	resp, err := d.sendRequest("POST", url, record)
+	resp, err := d.sendRequest(http.MethodPost, url, record)
 	if err != nil {
 		return err
 	}
@@ -187,7 +197,7 @@ func (d *DNSProvider) createRecord(domain *Domain, record *Record) error {
 func (d *DNSProvider) deleteRecord(record Record) error {
 	resource := fmt.Sprintf("%s/%d/%s/%d", "/dns/managed", record.SourceID, "records", record.ID)
 
-	resp, err := d.sendRequest("DELETE", resource, nil)
+	resp, err := d.sendRequest(http.MethodDelete, resource, nil)
 	if err != nil {
 		return err
 	}
@@ -217,14 +227,7 @@ func (d *DNSProvider) sendRequest(method, resource string, payload interface{})
 	req.Header.Set("accept", "application/json")
 	req.Header.Set("content-type", "application/json")
 
-	transport := &http.Transport{
-		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
-	}
-	client := &http.Client{
-		Transport: transport,
-		Timeout:   10 * time.Second,
-	}
-	resp, err := client.Do(req)
+	resp, err := d.client.Do(req)
 	if err != nil {
 		return nil, err
 	}
diff --git a/providers/dns/dnspod/dnspod.go b/providers/dns/dnspod/dnspod.go
index bfbeee62..e42e3633 100644
--- a/providers/dns/dnspod/dnspod.go
+++ b/providers/dns/dnspod/dnspod.go
@@ -41,15 +41,15 @@ func NewDNSProviderCredentials(key string) (*DNSProvider, error) {
 }
 
 // Present creates a TXT record to fulfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-	zoneID, zoneName, err := c.getHostedZone(domain)
+	zoneID, zoneName, err := d.getHostedZone(domain)
 	if err != nil {
 		return err
 	}
 
-	recordAttributes := c.newTxtRecord(zoneName, fqdn, value, ttl)
-	_, _, err = c.client.Domains.CreateRecord(zoneID, *recordAttributes)
+	recordAttributes := d.newTxtRecord(zoneName, fqdn, value, ttl)
+	_, _, err = d.client.Domains.CreateRecord(zoneID, *recordAttributes)
 	if err != nil {
 		return fmt.Errorf("dnspod API call failed: %v", err)
 	}
@@ -58,21 +58,21 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 }
 
 // CleanUp removes the TXT record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
 
-	records, err := c.findTxtRecords(domain, fqdn)
+	records, err := d.findTxtRecords(domain, fqdn)
 	if err != nil {
 		return err
 	}
 
-	zoneID, _, err := c.getHostedZone(domain)
+	zoneID, _, err := d.getHostedZone(domain)
 	if err != nil {
 		return err
 	}
 
 	for _, rec := range records {
-		_, err := c.client.Domains.DeleteRecord(zoneID, rec.ID)
+		_, err := d.client.Domains.DeleteRecord(zoneID, rec.ID)
 		if err != nil {
 			return err
 		}
@@ -80,8 +80,8 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	return nil
 }
 
-func (c *DNSProvider) getHostedZone(domain string) (string, string, error) {
-	zones, _, err := c.client.Domains.List()
+func (d *DNSProvider) getHostedZone(domain string) (string, string, error) {
+	zones, _, err := d.client.Domains.List()
 	if err != nil {
 		return "", "", fmt.Errorf("dnspod API call failed: %v", err)
 	}
@@ -106,8 +106,8 @@ func (c *DNSProvider) getHostedZone(domain string) (string, string, error) {
 	return fmt.Sprintf("%v", hostedZone.ID), hostedZone.Name, nil
 }
 
-func (c *DNSProvider) newTxtRecord(zone, fqdn, value string, ttl int) *dnspod.Record {
-	name := c.extractRecordName(fqdn, zone)
+func (d *DNSProvider) newTxtRecord(zone, fqdn, value string, ttl int) *dnspod.Record {
+	name := d.extractRecordName(fqdn, zone)
 
 	return &dnspod.Record{
 		Type:  "TXT",
@@ -118,19 +118,19 @@ func (c *DNSProvider) newTxtRecord(zone, fqdn, value string, ttl int) *dnspod.Re
 	}
 }
 
-func (c *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnspod.Record, error) {
-	zoneID, zoneName, err := c.getHostedZone(domain)
+func (d *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnspod.Record, error) {
+	zoneID, zoneName, err := d.getHostedZone(domain)
 	if err != nil {
 		return nil, err
 	}
 
 	var records []dnspod.Record
-	result, _, err := c.client.Domains.ListRecords(zoneID, "")
+	result, _, err := d.client.Domains.ListRecords(zoneID, "")
 	if err != nil {
 		return records, fmt.Errorf("dnspod API call has failed: %v", err)
 	}
 
-	recordName := c.extractRecordName(fqdn, zoneName)
+	recordName := d.extractRecordName(fqdn, zoneName)
 
 	for _, record := range result {
 		if record.Name == recordName {
@@ -141,7 +141,7 @@ func (c *DNSProvider) findTxtRecords(domain, fqdn string) ([]dnspod.Record, erro
 	return records, nil
 }
 
-func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
+func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
 	name := acme.UnFqdn(fqdn)
 	if idx := strings.Index(name, "."+domain); idx != -1 {
 		return name[:idx]
diff --git a/providers/dns/dyn/dyn.go b/providers/dns/dyn/dyn.go
index 27e6f7ed..187b1b48 100644
--- a/providers/dns/dyn/dyn.go
+++ b/providers/dns/dyn/dyn.go
@@ -37,6 +37,7 @@ type DNSProvider struct {
 	userName     string
 	password     string
 	token        string
+	client       *http.Client
 }
 
 // NewDNSProvider returns a DNSProvider instance configured for Dyn DNS.
@@ -62,6 +63,7 @@ func NewDNSProviderCredentials(customerName, userName, password string) (*DNSPro
 		customerName: customerName,
 		userName:     userName,
 		password:     password,
+		client:       &http.Client{Timeout: 10 * time.Second},
 	}, nil
 }
 
@@ -82,8 +84,7 @@ func (d *DNSProvider) sendRequest(method, resource string, payload interface{})
 		req.Header.Set("Auth-Token", d.token)
 	}
 
-	client := &http.Client{Timeout: 10 * time.Second}
-	resp, err := client.Do(req)
+	resp, err := d.client.Do(req)
 	if err != nil {
 		return nil, err
 	}
@@ -129,7 +130,7 @@ func (d *DNSProvider) login() error {
 	}
 
 	payload := &creds{Customer: d.customerName, User: d.userName, Pass: d.password}
-	dynRes, err := d.sendRequest("POST", "Session", payload)
+	dynRes, err := d.sendRequest(http.MethodPost, "Session", payload)
 	if err != nil {
 		return err
 	}
@@ -153,15 +154,14 @@ func (d *DNSProvider) logout() error {
 	}
 
 	url := fmt.Sprintf("%s/Session", dynBaseURL)
-	req, err := http.NewRequest("DELETE", url, nil)
+	req, err := http.NewRequest(http.MethodDelete, url, nil)
 	if err != nil {
 		return err
 	}
 	req.Header.Set("Content-Type", "application/json")
 	req.Header.Set("Auth-Token", d.token)
 
-	client := &http.Client{Timeout: 10 * time.Second}
-	resp, err := client.Do(req)
+	resp, err := d.client.Do(req)
 	if err != nil {
 		return err
 	}
@@ -198,7 +198,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	}
 
 	resource := fmt.Sprintf("TXTRecord/%s/%s/", authZone, fqdn)
-	_, err = d.sendRequest("POST", resource, data)
+	_, err = d.sendRequest(http.MethodPost, resource, data)
 	if err != nil {
 		return err
 	}
@@ -220,7 +220,7 @@ func (d *DNSProvider) publish(zone, notes string) error {
 	pub := &publish{Publish: true, Notes: notes}
 	resource := fmt.Sprintf("Zone/%s/", zone)
 
-	_, err := d.sendRequest("PUT", resource, pub)
+	_, err := d.sendRequest(http.MethodPut, resource, pub)
 	return err
 }
 
@@ -240,15 +240,16 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 
 	resource := fmt.Sprintf("TXTRecord/%s/%s/", authZone, fqdn)
 	url := fmt.Sprintf("%s/%s", dynBaseURL, resource)
-	req, err := http.NewRequest("DELETE", url, nil)
+
+	req, err := http.NewRequest(http.MethodDelete, url, nil)
 	if err != nil {
 		return err
 	}
+
 	req.Header.Set("Content-Type", "application/json")
 	req.Header.Set("Auth-Token", d.token)
 
-	client := &http.Client{Timeout: 10 * time.Second}
-	resp, err := client.Do(req)
+	resp, err := d.client.Do(req)
 	if err != nil {
 		return err
 	}
diff --git a/providers/dns/exoscale/exoscale.go b/providers/dns/exoscale/exoscale.go
index 421a3b40..c5b26d1d 100644
--- a/providers/dns/exoscale/exoscale.go
+++ b/providers/dns/exoscale/exoscale.go
@@ -46,14 +46,14 @@ func NewDNSProviderClient(key, secret, endpoint string) (*DNSProvider, error) {
 }
 
 // Present creates a TXT record to fulfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-	zone, recordName, err := c.FindZoneAndRecordName(fqdn, domain)
+	zone, recordName, err := d.FindZoneAndRecordName(fqdn, domain)
 	if err != nil {
 		return err
 	}
 
-	recordID, err := c.FindExistingRecordID(zone, recordName)
+	recordID, err := d.FindExistingRecordID(zone, recordName)
 	if err != nil {
 		return err
 	}
@@ -66,13 +66,13 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 	}
 
 	if recordID == 0 {
-		_, err := c.client.CreateRecord(zone, record)
+		_, err := d.client.CreateRecord(zone, record)
 		if err != nil {
 			return errors.New("Error while creating DNS record: " + err.Error())
 		}
 	} else {
 		record.ID = recordID
-		_, err := c.client.UpdateRecord(zone, record)
+		_, err := d.client.UpdateRecord(zone, record)
 		if err != nil {
 			return errors.New("Error while updating DNS record: " + err.Error())
 		}
@@ -82,20 +82,20 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 }
 
 // CleanUp removes the record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-	zone, recordName, err := c.FindZoneAndRecordName(fqdn, domain)
+	zone, recordName, err := d.FindZoneAndRecordName(fqdn, domain)
 	if err != nil {
 		return err
 	}
 
-	recordID, err := c.FindExistingRecordID(zone, recordName)
+	recordID, err := d.FindExistingRecordID(zone, recordName)
 	if err != nil {
 		return err
 	}
 
 	if recordID != 0 {
-		err = c.client.DeleteRecord(zone, recordID)
+		err = d.client.DeleteRecord(zone, recordID)
 		if err != nil {
 			return errors.New("Error while deleting DNS record: " + err.Error())
 		}
@@ -106,8 +106,8 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 
 // FindExistingRecordID Query Exoscale to find an existing record for this name.
 // Returns nil if no record could be found
-func (c *DNSProvider) FindExistingRecordID(zone, recordName string) (int64, error) {
-	records, err := c.client.GetRecords(zone)
+func (d *DNSProvider) FindExistingRecordID(zone, recordName string) (int64, error) {
+	records, err := d.client.GetRecords(zone)
 	if err != nil {
 		return -1, errors.New("Error while retrievening DNS records: " + err.Error())
 	}
@@ -120,7 +120,7 @@ func (c *DNSProvider) FindExistingRecordID(zone, recordName string) (int64, erro
 }
 
 // FindZoneAndRecordName Extract DNS zone and DNS entry name
-func (c *DNSProvider) FindZoneAndRecordName(fqdn, domain string) (string, string, error) {
+func (d *DNSProvider) FindZoneAndRecordName(fqdn, domain string) (string, string, error) {
 	zone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
 	if err != nil {
 		return "", "", err
diff --git a/providers/dns/fastdns/fastdns.go b/providers/dns/fastdns/fastdns.go
index 78249127..4bc79400 100644
--- a/providers/dns/fastdns/fastdns.go
+++ b/providers/dns/fastdns/fastdns.go
@@ -51,14 +51,14 @@ func NewDNSProviderClient(host, clientToken, clientSecret, accessToken string) (
 }
 
 // Present creates a TXT record to fullfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-	zoneName, recordName, err := c.findZoneAndRecordName(fqdn, domain)
+	zoneName, recordName, err := d.findZoneAndRecordName(fqdn, domain)
 	if err != nil {
 		return err
 	}
 
-	configdns.Init(c.config)
+	configdns.Init(d.config)
 
 	zone, err := configdns.GetZone(zoneName)
 	if err != nil {
@@ -71,35 +71,35 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 	record.SetField("target", value)
 	record.SetField("active", true)
 
-	existingRecord := c.findExistingRecord(zone, recordName)
+	existingRecord := d.findExistingRecord(zone, recordName)
 
 	if existingRecord != nil {
 		if reflect.DeepEqual(existingRecord.ToMap(), record.ToMap()) {
 			return nil
 		}
 		zone.RemoveRecord(existingRecord)
-		return c.createRecord(zone, record)
+		return d.createRecord(zone, record)
 	}
 
-	return c.createRecord(zone, record)
+	return d.createRecord(zone, record)
 }
 
 // CleanUp removes the record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-	zoneName, recordName, err := c.findZoneAndRecordName(fqdn, domain)
+	zoneName, recordName, err := d.findZoneAndRecordName(fqdn, domain)
 	if err != nil {
 		return err
 	}
 
-	configdns.Init(c.config)
+	configdns.Init(d.config)
 
 	zone, err := configdns.GetZone(zoneName)
 	if err != nil {
 		return err
 	}
 
-	existingRecord := c.findExistingRecord(zone, recordName)
+	existingRecord := d.findExistingRecord(zone, recordName)
 
 	if existingRecord != nil {
 		err := zone.RemoveRecord(existingRecord)
@@ -112,7 +112,7 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	return nil
 }
 
-func (c *DNSProvider) findZoneAndRecordName(fqdn, domain string) (string, string, error) {
+func (d *DNSProvider) findZoneAndRecordName(fqdn, domain string) (string, string, error) {
 	zone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
 	if err != nil {
 		return "", "", err
@@ -124,7 +124,7 @@ func (c *DNSProvider) findZoneAndRecordName(fqdn, domain string) (string, string
 	return zone, name, nil
 }
 
-func (c *DNSProvider) findExistingRecord(zone *configdns.Zone, recordName string) *configdns.TxtRecord {
+func (d *DNSProvider) findExistingRecord(zone *configdns.Zone, recordName string) *configdns.TxtRecord {
 	for _, r := range zone.Zone.Txt {
 		if r.Name == recordName {
 			return r
@@ -134,7 +134,7 @@ func (c *DNSProvider) findExistingRecord(zone *configdns.Zone, recordName string
 	return nil
 }
 
-func (c *DNSProvider) createRecord(zone *configdns.Zone, record *configdns.TxtRecord) error {
+func (d *DNSProvider) createRecord(zone *configdns.Zone, record *configdns.TxtRecord) error {
 	err := zone.AddRecord(record)
 	if err != nil {
 		return err
diff --git a/providers/dns/gandi/gandi.go b/providers/dns/gandi/gandi.go
index fa43f581..d7243009 100644
--- a/providers/dns/gandi/gandi.go
+++ b/providers/dns/gandi/gandi.go
@@ -44,6 +44,7 @@ type DNSProvider struct {
 	inProgressFQDNs     map[string]inProgressInfo
 	inProgressAuthZones map[string]struct{}
 	inProgressMu        sync.Mutex
+	client              *http.Client
 }
 
 // NewDNSProvider returns a DNSProvider instance configured for Gandi.
@@ -61,12 +62,13 @@ func NewDNSProvider() (*DNSProvider, error) {
 // DNSProvider instance configured for Gandi.
 func NewDNSProviderCredentials(apiKey string) (*DNSProvider, error) {
 	if apiKey == "" {
-		return nil, fmt.Errorf("No Gandi API Key given")
+		return nil, fmt.Errorf("no Gandi API Key given")
 	}
 	return &DNSProvider{
 		apiKey:              apiKey,
 		inProgressFQDNs:     make(map[string]inProgressInfo),
 		inProgressAuthZones: make(map[string]struct{}),
+		client:              &http.Client{Timeout: 60 * time.Second},
 	}, nil
 }
 
@@ -273,10 +275,8 @@ func (e rpcError) Error() string {
 		"Gandi DNS: RPC Error: (%d) %s", e.faultCode, e.faultString)
 }
 
-func httpPost(url string, bodyType string, body io.Reader) ([]byte, error) {
-	client := http.Client{Timeout: 60 * time.Second}
-
-	resp, err := client.Post(url, bodyType, body)
+func (d *DNSProvider) httpPost(url string, bodyType string, body io.Reader) ([]byte, error) {
+	resp, err := d.client.Post(url, bodyType, body)
 	if err != nil {
 		return nil, fmt.Errorf("Gandi DNS: HTTP Post Error: %v", err)
 	}
@@ -294,7 +294,7 @@ func httpPost(url string, bodyType string, body io.Reader) ([]byte, error) {
 // marshalling the data given in the call argument to XML and sending
 // that via HTTP Post to Gandi. The response is then unmarshalled into
 // the resp argument.
-func rpcCall(call *methodCall, resp response) error {
+func (d *DNSProvider) rpcCall(call *methodCall, resp response) error {
 	// marshal
 	b, err := xml.MarshalIndent(call, "", "  ")
 	if err != nil {
@@ -303,7 +303,7 @@ func rpcCall(call *methodCall, resp response) error {
 
 	// post
 	b = append([]byte(`<?xml version="1.0"?>`+"\n"), b...)
-	respBody, err := httpPost(endpoint, "text/xml", bytes.NewReader(b))
+	respBody, err := d.httpPost(endpoint, "text/xml", bytes.NewReader(b))
 	if err != nil {
 		return err
 	}
@@ -324,7 +324,7 @@ func rpcCall(call *methodCall, resp response) error {
 
 func (d *DNSProvider) getZoneID(domain string) (int, error) {
 	resp := &responseStruct{}
-	err := rpcCall(&methodCall{
+	err := d.rpcCall(&methodCall{
 		MethodName: "domain.info",
 		Params: []param{
 			paramString{Value: d.apiKey},
@@ -351,7 +351,7 @@ func (d *DNSProvider) getZoneID(domain string) (int, error) {
 
 func (d *DNSProvider) cloneZone(zoneID int, name string) (int, error) {
 	resp := &responseStruct{}
-	err := rpcCall(&methodCall{
+	err := d.rpcCall(&methodCall{
 		MethodName: "domain.zone.clone",
 		Params: []param{
 			paramString{Value: d.apiKey},
@@ -385,7 +385,7 @@ func (d *DNSProvider) cloneZone(zoneID int, name string) (int, error) {
 
 func (d *DNSProvider) newZoneVersion(zoneID int) (int, error) {
 	resp := &responseInt{}
-	err := rpcCall(&methodCall{
+	err := d.rpcCall(&methodCall{
 		MethodName: "domain.zone.version.new",
 		Params: []param{
 			paramString{Value: d.apiKey},
@@ -404,7 +404,7 @@ func (d *DNSProvider) newZoneVersion(zoneID int) (int, error) {
 
 func (d *DNSProvider) addTXTRecord(zoneID int, version int, name string, value string, ttl int) error {
 	resp := &responseStruct{}
-	err := rpcCall(&methodCall{
+	err := d.rpcCall(&methodCall{
 		MethodName: "domain.zone.record.add",
 		Params: []param{
 			paramString{Value: d.apiKey},
@@ -433,7 +433,7 @@ func (d *DNSProvider) addTXTRecord(zoneID int, version int, name string, value s
 
 func (d *DNSProvider) setZoneVersion(zoneID int, version int) error {
 	resp := &responseBool{}
-	err := rpcCall(&methodCall{
+	err := d.rpcCall(&methodCall{
 		MethodName: "domain.zone.version.set",
 		Params: []param{
 			paramString{Value: d.apiKey},
@@ -453,7 +453,7 @@ func (d *DNSProvider) setZoneVersion(zoneID int, version int) error {
 
 func (d *DNSProvider) setZone(domain string, zoneID int) error {
 	resp := &responseStruct{}
-	err := rpcCall(&methodCall{
+	err := d.rpcCall(&methodCall{
 		MethodName: "domain.zone.set",
 		Params: []param{
 			paramString{Value: d.apiKey},
@@ -481,7 +481,7 @@ func (d *DNSProvider) setZone(domain string, zoneID int) error {
 
 func (d *DNSProvider) deleteZone(zoneID int) error {
 	resp := &responseBool{}
-	err := rpcCall(&methodCall{
+	err := d.rpcCall(&methodCall{
 		MethodName: "domain.zone.delete",
 		Params: []param{
 			paramString{Value: d.apiKey},
diff --git a/providers/dns/gandiv5/gandiv5.go b/providers/dns/gandiv5/gandiv5.go
index c0dff4d1..dea0f5f4 100644
--- a/providers/dns/gandiv5/gandiv5.go
+++ b/providers/dns/gandiv5/gandiv5.go
@@ -12,6 +12,7 @@ import (
 	"time"
 
 	"github.com/xenolf/lego/acme"
+	"github.com/xenolf/lego/log"
 	"github.com/xenolf/lego/platform/config/env"
 )
 
@@ -40,6 +41,7 @@ type DNSProvider struct {
 	apiKey          string
 	inProgressFQDNs map[string]inProgressInfo
 	inProgressMu    sync.Mutex
+	client          *http.Client
 }
 
 // NewDNSProvider returns a DNSProvider instance configured for Gandi.
@@ -62,6 +64,7 @@ func NewDNSProviderCredentials(apiKey string) (*DNSProvider, error) {
 	return &DNSProvider{
 		apiKey:          apiKey,
 		inProgressFQDNs: make(map[string]inProgressInfo),
+		client:          &http.Client{Timeout: 10 * time.Second},
 	}, nil
 }
 
@@ -169,8 +172,7 @@ func (d *DNSProvider) sendRequest(method string, resource string, payload interf
 		req.Header.Set("X-Api-Key", d.apiKey)
 	}
 
-	client := &http.Client{Timeout: 10 * time.Second}
-	resp, err := client.Do(req)
+	resp, err := d.client.Do(req)
 	if err != nil {
 		return nil, err
 	}
@@ -181,7 +183,7 @@ func (d *DNSProvider) sendRequest(method string, resource string, payload interf
 	}
 	var response responseStruct
 	err = json.NewDecoder(resp.Body).Decode(&response)
-	if err != nil && method != "DELETE" {
+	if err != nil && method != http.MethodDelete {
 		return nil, err
 	}
 
@@ -192,23 +194,23 @@ func (d *DNSProvider) sendRequest(method string, resource string, payload interf
 
 func (d *DNSProvider) addTXTRecord(domain string, name string, value string, ttl int) error {
 	target := fmt.Sprintf("domains/%s/records/%s/TXT", domain, name)
-	response, err := d.sendRequest("PUT", target, addFieldRequest{
+	response, err := d.sendRequest(http.MethodPut, target, addFieldRequest{
 		RRSetTTL:    ttl,
 		RRSetValues: []string{value},
 	})
 	if response != nil {
-		fmt.Printf("Gandi DNS: %s\n", response.Message)
+		log.Infof("Gandi DNS: %s", response.Message)
 	}
 	return err
 }
 
 func (d *DNSProvider) deleteTXTRecord(domain string, name string) error {
 	target := fmt.Sprintf("domains/%s/records/%s/TXT", domain, name)
-	response, err := d.sendRequest("DELETE", target, deleteFieldRequest{
+	response, err := d.sendRequest(http.MethodDelete, target, deleteFieldRequest{
 		Delete: true,
 	})
 	if response != nil && response.Message == "" {
-		fmt.Printf("Gandi DNS: Zone record deleted\n")
+		log.Infof("Gandi DNS: Zone record deleted")
 	}
 	return err
 }
diff --git a/providers/dns/gcloud/googlecloud.go b/providers/dns/gcloud/googlecloud.go
index c50c0ed7..2999a79d 100644
--- a/providers/dns/gcloud/googlecloud.go
+++ b/providers/dns/gcloud/googlecloud.go
@@ -96,10 +96,10 @@ func NewDNSProviderServiceAccount(saFile string) (*DNSProvider, error) {
 }
 
 // Present creates a TXT record to fulfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
 
-	zone, err := c.getHostedZone(domain)
+	zone, err := d.getHostedZone(domain)
 	if err != nil {
 		return err
 	}
@@ -115,7 +115,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 	}
 
 	// Look for existing records.
-	list, err := c.client.ResourceRecordSets.List(c.project, zone).Name(fqdn).Type("TXT").Do()
+	list, err := d.client.ResourceRecordSets.List(d.project, zone).Name(fqdn).Type("TXT").Do()
 	if err != nil {
 		return err
 	}
@@ -124,7 +124,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 		change.Deletions = list.Rrsets
 	}
 
-	chg, err := c.client.Changes.Create(c.project, zone, change).Do()
+	chg, err := d.client.Changes.Create(d.project, zone, change).Do()
 	if err != nil {
 		return err
 	}
@@ -133,7 +133,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 	for chg.Status == "pending" {
 		time.Sleep(time.Second)
 
-		chg, err = c.client.Changes.Get(c.project, zone, chg.Id).Do()
+		chg, err = d.client.Changes.Get(d.project, zone, chg.Id).Do()
 		if err != nil {
 			return err
 		}
@@ -143,15 +143,15 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 }
 
 // CleanUp removes the TXT record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
 
-	zone, err := c.getHostedZone(domain)
+	zone, err := d.getHostedZone(domain)
 	if err != nil {
 		return err
 	}
 
-	records, err := c.findTxtRecords(zone, fqdn)
+	records, err := d.findTxtRecords(zone, fqdn)
 	if err != nil {
 		return err
 	}
@@ -160,7 +160,7 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 		change := &dns.Change{
 			Deletions: []*dns.ResourceRecordSet{rec},
 		}
-		_, err = c.client.Changes.Create(c.project, zone, change).Do()
+		_, err = d.client.Changes.Create(d.project, zone, change).Do()
 		if err != nil {
 			return err
 		}
@@ -170,19 +170,19 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 
 // Timeout customizes the timeout values used by the ACME package for checking
 // DNS record validity.
-func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
+func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
 	return 180 * time.Second, 5 * time.Second
 }
 
 // getHostedZone returns the managed-zone
-func (c *DNSProvider) getHostedZone(domain string) (string, error) {
+func (d *DNSProvider) getHostedZone(domain string) (string, error) {
 	authZone, err := acme.FindZoneByFqdn(acme.ToFqdn(domain), acme.RecursiveNameservers)
 	if err != nil {
 		return "", err
 	}
 
-	zones, err := c.client.ManagedZones.
-		List(c.project).
+	zones, err := d.client.ManagedZones.
+		List(d.project).
 		DnsName(authZone).
 		Do()
 	if err != nil {
@@ -196,9 +196,9 @@ func (c *DNSProvider) getHostedZone(domain string) (string, error) {
 	return zones.ManagedZones[0].Name, nil
 }
 
-func (c *DNSProvider) findTxtRecords(zone, fqdn string) ([]*dns.ResourceRecordSet, error) {
+func (d *DNSProvider) findTxtRecords(zone, fqdn string) ([]*dns.ResourceRecordSet, error) {
 
-	recs, err := c.client.ResourceRecordSets.List(c.project, zone).Do()
+	recs, err := d.client.ResourceRecordSets.List(d.project, zone).Do()
 	if err != nil {
 		return nil, err
 	}
diff --git a/providers/dns/glesys/glesys.go b/providers/dns/glesys/glesys.go
index 71ef461f..d6b07196 100644
--- a/providers/dns/glesys/glesys.go
+++ b/providers/dns/glesys/glesys.go
@@ -29,6 +29,7 @@ type DNSProvider struct {
 	apiKey        string
 	activeRecords map[string]int
 	inProgressMu  sync.Mutex
+	client        *http.Client
 }
 
 // NewDNSProvider returns a DNSProvider instance configured for GleSYS.
@@ -49,10 +50,12 @@ func NewDNSProviderCredentials(apiUser string, apiKey string) (*DNSProvider, err
 	if apiUser == "" || apiKey == "" {
 		return nil, fmt.Errorf("GleSYS DNS: Incomplete credentials provided")
 	}
+
 	return &DNSProvider{
 		apiUser:       apiUser,
 		apiKey:        apiKey,
 		activeRecords: make(map[string]int),
+		client:        &http.Client{Timeout: 10 * time.Second},
 	}, nil
 }
 
@@ -121,7 +124,7 @@ func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
 // types for JSON method calls, parameters, and responses
 
 type addRecordRequest struct {
-	Domainname string `json:"domainname"`
+	DomainName string `json:"domainname"`
 	Host       string `json:"host"`
 	Type       string `json:"type"`
 	Data       string `json:"data"`
@@ -129,7 +132,7 @@ type addRecordRequest struct {
 }
 
 type deleteRecordRequest struct {
-	Recordid int `json:"recordid"`
+	RecordID int `json:"recordid"`
 }
 
 type responseStruct struct {
@@ -159,8 +162,7 @@ func (d *DNSProvider) sendRequest(method string, resource string, payload interf
 	req.Header.Set("Content-Type", "application/json")
 	req.SetBasicAuth(d.apiUser, d.apiKey)
 
-	client := &http.Client{Timeout: 10 * time.Second}
-	resp, err := client.Do(req)
+	resp, err := d.client.Do(req)
 	if err != nil {
 		return nil, err
 	}
@@ -179,26 +181,27 @@ func (d *DNSProvider) sendRequest(method string, resource string, payload interf
 // functions to perform API actions
 
 func (d *DNSProvider) addTXTRecord(fqdn string, domain string, name string, value string, ttl int) (int, error) {
-	response, err := d.sendRequest("POST", "addrecord", addRecordRequest{
-		Domainname: domain,
+	response, err := d.sendRequest(http.MethodPost, "addrecord", addRecordRequest{
+		DomainName: domain,
 		Host:       name,
 		Type:       "TXT",
 		Data:       value,
 		TTL:        ttl,
 	})
-	if response != nil && response.Response.Status.Code == 200 {
-		log.Printf("[INFO][%s] GleSYS DNS: Successfully created recordid %d", fqdn, response.Response.Record.Recordid)
-		return response.Response.Record.Recordid, nil
+
+	if response != nil && response.Response.Status.Code == http.StatusOK {
+		log.Infof("[%s] GleSYS DNS: Successfully created record id %d", fqdn, response.Response.Record.RecordID)
+		return response.Response.Record.RecordID, nil
 	}
 	return 0, err
 }
 
 func (d *DNSProvider) deleteTXTRecord(fqdn string, recordid int) error {
-	response, err := d.sendRequest("POST", "deleterecord", deleteRecordRequest{
-		Recordid: recordid,
+	response, err := d.sendRequest(http.MethodPost, "deleterecord", deleteRecordRequest{
+		RecordID: recordid,
 	})
 	if response != nil && response.Response.Status.Code == 200 {
-		log.Printf("[INFO][%s] GleSYS DNS: Successfully deleted recordid %d", fqdn, recordid)
+		log.Infof("[%s] GleSYS DNS: Successfully deleted record id %d", fqdn, recordid)
 	}
 	return err
 }
diff --git a/providers/dns/godaddy/godaddy.go b/providers/dns/godaddy/godaddy.go
index 75716b8a..c569adcb 100644
--- a/providers/dns/godaddy/godaddy.go
+++ b/providers/dns/godaddy/godaddy.go
@@ -22,6 +22,7 @@ const apiURL = "https://api.godaddy.com"
 type DNSProvider struct {
 	apiKey    string
 	apiSecret string
+	client    *http.Client
 }
 
 // NewDNSProvider returns a DNSProvider instance configured for godaddy.
@@ -43,16 +44,20 @@ func NewDNSProviderCredentials(apiKey, apiSecret string) (*DNSProvider, error) {
 		return nil, fmt.Errorf("GoDaddy credentials missing")
 	}
 
-	return &DNSProvider{apiKey, apiSecret}, nil
+	return &DNSProvider{
+		apiKey:    apiKey,
+		apiSecret: apiSecret,
+		client:    &http.Client{Timeout: 30 * time.Second},
+	}, nil
 }
 
 // Timeout returns the timeout and interval to use when checking for DNS
 // propagation. Adjusting here to cope with spikes in propagation times.
-func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
+func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
 	return 120 * time.Second, 2 * time.Second
 }
 
-func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
+func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
 	name := acme.UnFqdn(fqdn)
 	if idx := strings.Index(name, "."+domain); idx != -1 {
 		return name[:idx]
@@ -61,9 +66,9 @@ func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
 }
 
 // Present creates a TXT record to fulfil the dns-01 challenge
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
-	domainZone, err := c.getZone(fqdn)
+	domainZone, err := d.getZone(fqdn)
 	if err != nil {
 		return err
 	}
@@ -72,7 +77,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 		ttl = 600
 	}
 
-	recordName := c.extractRecordName(fqdn, domainZone)
+	recordName := d.extractRecordName(fqdn, domainZone)
 	rec := []DNSRecord{
 		{
 			Type: "TXT",
@@ -82,17 +87,17 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 		},
 	}
 
-	return c.updateRecords(rec, domainZone, recordName)
+	return d.updateRecords(rec, domainZone, recordName)
 }
 
-func (c *DNSProvider) updateRecords(records []DNSRecord, domainZone string, recordName string) error {
+func (d *DNSProvider) updateRecords(records []DNSRecord, domainZone string, recordName string) error {
 	body, err := json.Marshal(records)
 	if err != nil {
 		return err
 	}
 
 	var resp *http.Response
-	resp, err = c.makeRequest("PUT", fmt.Sprintf("/v1/domains/%s/records/TXT/%s", domainZone, recordName), bytes.NewReader(body))
+	resp, err = d.makeRequest(http.MethodPut, fmt.Sprintf("/v1/domains/%s/records/TXT/%s", domainZone, recordName), bytes.NewReader(body))
 	if err != nil {
 		return err
 	}
@@ -107,14 +112,14 @@ func (c *DNSProvider) updateRecords(records []DNSRecord, domainZone string, reco
 }
 
 // CleanUp sets null value in the TXT DNS record as GoDaddy has no proper DELETE record method
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-	domainZone, err := c.getZone(fqdn)
+	domainZone, err := d.getZone(fqdn)
 	if err != nil {
 		return err
 	}
 
-	recordName := c.extractRecordName(fqdn, domainZone)
+	recordName := d.extractRecordName(fqdn, domainZone)
 	rec := []DNSRecord{
 		{
 			Type: "TXT",
@@ -123,10 +128,10 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 		},
 	}
 
-	return c.updateRecords(rec, domainZone, recordName)
+	return d.updateRecords(rec, domainZone, recordName)
 }
 
-func (c *DNSProvider) getZone(fqdn string) (string, error) {
+func (d *DNSProvider) getZone(fqdn string) (string, error) {
 	authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
 	if err != nil {
 		return "", err
@@ -135,7 +140,7 @@ func (c *DNSProvider) getZone(fqdn string) (string, error) {
 	return acme.UnFqdn(authZone), nil
 }
 
-func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (*http.Response, error) {
+func (d *DNSProvider) makeRequest(method, uri string, body io.Reader) (*http.Response, error) {
 	req, err := http.NewRequest(method, fmt.Sprintf("%s%s", apiURL, uri), body)
 	if err != nil {
 		return nil, err
@@ -143,10 +148,9 @@ func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (*http.Res
 
 	req.Header.Set("Accept", "application/json")
 	req.Header.Set("Content-Type", "application/json")
-	req.Header.Set("Authorization", fmt.Sprintf("sso-key %s:%s", c.apiKey, c.apiSecret))
+	req.Header.Set("Authorization", fmt.Sprintf("sso-key %s:%s", d.apiKey, d.apiSecret))
 
-	client := http.Client{Timeout: 30 * time.Second}
-	return client.Do(req)
+	return d.client.Do(req)
 }
 
 // DNSRecord a DNS record
diff --git a/providers/dns/lightsail/lightsail.go b/providers/dns/lightsail/lightsail.go
index a4d2efaf..2f6feddd 100644
--- a/providers/dns/lightsail/lightsail.go
+++ b/providers/dns/lightsail/lightsail.go
@@ -35,7 +35,7 @@ type customRetryer struct {
 // delay of ~400ms with an upper limit of ~30 seconds which should prevent
 // causing a high number of consecutive throttling errors.
 // For reference: Route 53 enforces an account-wide(!) 5req/s query limit.
-func (d customRetryer) RetryRules(r *request.Request) time.Duration {
+func (c customRetryer) RetryRules(r *request.Request) time.Duration {
 	retryCount := r.RetryCount
 	if retryCount > 7 {
 		retryCount = 7
@@ -70,15 +70,15 @@ func NewDNSProvider() (*DNSProvider, error) {
 }
 
 // Present creates a TXT record using the specified parameters
-func (r *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
 	value = `"` + value + `"`
-	err := r.newTxtRecord(domain, fqdn, value)
+	err := d.newTxtRecord(domain, fqdn, value)
 	return err
 }
 
 // CleanUp removes the TXT record matching the specified parameters
-func (r *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
 	value = `"` + value + `"`
 	params := &lightsail.DeleteDomainEntryInput{
@@ -89,11 +89,11 @@ func (r *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 			Target: aws.String(value),
 		},
 	}
-	_, err := r.client.DeleteDomainEntry(params)
+	_, err := d.client.DeleteDomainEntry(params)
 	return err
 }
 
-func (r *DNSProvider) newTxtRecord(domain string, fqdn string, value string) error {
+func (d *DNSProvider) newTxtRecord(domain string, fqdn string, value string) error {
 	params := &lightsail.CreateDomainEntryInput{
 		DomainName: aws.String(domain),
 		DomainEntry: &lightsail.DomainEntry{
@@ -102,6 +102,6 @@ func (r *DNSProvider) newTxtRecord(domain string, fqdn string, value string) err
 			Type:   aws.String("TXT"),
 		},
 	}
-	_, err := r.client.CreateDomainEntry(params)
+	_, err := d.client.CreateDomainEntry(params)
 	return err
 }
diff --git a/providers/dns/linode/linode.go b/providers/dns/linode/linode.go
index 22117b66..087d8b19 100644
--- a/providers/dns/linode/linode.go
+++ b/providers/dns/linode/linode.go
@@ -26,7 +26,7 @@ type hostedZoneInfo struct {
 
 // DNSProvider implements the acme.ChallengeProvider interface.
 type DNSProvider struct {
-	linode *dns.DNS
+	client *dns.DNS
 }
 
 // NewDNSProvider returns a DNSProvider instance configured for Linode.
@@ -48,7 +48,7 @@ func NewDNSProviderCredentials(apiKey string) (*DNSProvider, error) {
 	}
 
 	return &DNSProvider{
-		linode: dns.New(apiKey),
+		client: dns.New(apiKey),
 	}, nil
 }
 
@@ -77,7 +77,7 @@ func (p *DNSProvider) Present(domain, token, keyAuth string) error {
 		return err
 	}
 
-	if _, err = p.linode.CreateDomainResourceTXT(zone.domainID, acme.UnFqdn(fqdn), value, 60); err != nil {
+	if _, err = p.client.CreateDomainResourceTXT(zone.domainID, acme.UnFqdn(fqdn), value, 60); err != nil {
 		return err
 	}
 
@@ -93,7 +93,7 @@ func (p *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	}
 
 	// Get all TXT records for the specified domain.
-	resources, err := p.linode.GetResourcesByType(zone.domainID, "TXT")
+	resources, err := p.client.GetResourcesByType(zone.domainID, "TXT")
 	if err != nil {
 		return err
 	}
@@ -101,7 +101,7 @@ func (p *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	// Remove the specified resource, if it exists.
 	for _, resource := range resources {
 		if resource.Name == zone.resourceName && resource.Target == value {
-			resp, err := p.linode.DeleteDomainResource(resource.DomainID, resource.ResourceID)
+			resp, err := p.client.DeleteDomainResource(resource.DomainID, resource.ResourceID)
 			if err != nil {
 				return err
 			}
@@ -124,7 +124,7 @@ func (p *DNSProvider) getHostedZoneInfo(fqdn string) (*hostedZoneInfo, error) {
 	resourceName := strings.TrimSuffix(fqdn, "."+authZone)
 
 	// Query the authority zone.
-	domain, err := p.linode.GetDomain(acme.UnFqdn(authZone))
+	domain, err := p.client.GetDomain(acme.UnFqdn(authZone))
 	if err != nil {
 		return nil, err
 	}
diff --git a/providers/dns/namecheap/namecheap.go b/providers/dns/namecheap/namecheap.go
index 35be8b4c..f0ce56a8 100644
--- a/providers/dns/namecheap/namecheap.go
+++ b/providers/dns/namecheap/namecheap.go
@@ -12,6 +12,7 @@ import (
 	"time"
 
 	"github.com/xenolf/lego/acme"
+	"github.com/xenolf/lego/log"
 	"github.com/xenolf/lego/platform/config/env"
 )
 
@@ -32,7 +33,6 @@ var (
 	debug          = false
 	defaultBaseURL = "https://api.namecheap.com/xml.response"
 	getIPURL       = "https://dynamicdns.park-your-domain.com/getip"
-	httpClient     = http.Client{Timeout: 60 * time.Second}
 )
 
 // DNSProvider is an implementation of the ChallengeProviderTimeout interface
@@ -42,6 +42,7 @@ type DNSProvider struct {
 	apiUser  string
 	apiKey   string
 	clientIP string
+	client   *http.Client
 }
 
 // NewDNSProvider returns a DNSProvider instance configured for namecheap.
@@ -63,7 +64,9 @@ func NewDNSProviderCredentials(apiUser, apiKey string) (*DNSProvider, error) {
 		return nil, fmt.Errorf("Namecheap credentials missing")
 	}
 
-	clientIP, err := getClientIP()
+	client := &http.Client{Timeout: 60 * time.Second}
+
+	clientIP, err := getClientIP(client)
 	if err != nil {
 		return nil, err
 	}
@@ -73,6 +76,7 @@ func NewDNSProviderCredentials(apiUser, apiKey string) (*DNSProvider, error) {
 		apiUser:  apiUser,
 		apiKey:   apiKey,
 		clientIP: clientIP,
+		client:   client,
 	}, nil
 }
 
@@ -102,8 +106,8 @@ type apierror struct {
 
 // getClientIP returns the client's public IP address. It uses namecheap's
 // IP discovery service to perform the lookup.
-func getClientIP() (addr string, err error) {
-	resp, err := httpClient.Get(getIPURL)
+func getClientIP(client *http.Client) (addr string, err error) {
+	resp, err := client.Get(getIPURL)
 	if err != nil {
 		return "", err
 	}
@@ -115,7 +119,7 @@ func getClientIP() (addr string, err error) {
 	}
 
 	if debug {
-		fmt.Println("Client IP:", string(clientIP))
+		log.Println("Client IP:", string(clientIP))
 	}
 	return string(clientIP), nil
 }
@@ -189,7 +193,7 @@ func (d *DNSProvider) getTLDs() (tlds map[string]string, err error) {
 	reqURL, _ := url.Parse(d.baseURL)
 	reqURL.RawQuery = values.Encode()
 
-	resp, err := httpClient.Get(reqURL.String())
+	resp, err := d.client.Get(reqURL.String())
 	if err != nil {
 		return nil, err
 	}
@@ -238,7 +242,7 @@ func (d *DNSProvider) getHosts(ch *challenge) (hosts []host, err error) {
 	reqURL, _ := url.Parse(d.baseURL)
 	reqURL.RawQuery = values.Encode()
 
-	resp, err := httpClient.Get(reqURL.String())
+	resp, err := d.client.Get(reqURL.String())
 	if err != nil {
 		return nil, err
 	}
@@ -288,7 +292,7 @@ func (d *DNSProvider) setHosts(ch *challenge, hosts []host) error {
 		values.Add("TTL"+ind, h.TTL)
 	}
 
-	resp, err := httpClient.PostForm(d.baseURL, values)
+	resp, err := d.client.PostForm(d.baseURL, values)
 	if err != nil {
 		return err
 	}
@@ -385,7 +389,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 
 	if debug {
 		for _, h := range hosts {
-			fmt.Printf(
+			log.Printf(
 				"%-5.5s %-30.30s %-6s %-70.70s\n",
 				h.Type, h.Name, h.TTL, h.Address)
 		}
diff --git a/providers/dns/namedotcom/namedotcom.go b/providers/dns/namedotcom/namedotcom.go
index 39c0cca9..15272c5f 100644
--- a/providers/dns/namedotcom/namedotcom.go
+++ b/providers/dns/namedotcom/namedotcom.go
@@ -49,18 +49,18 @@ func NewDNSProviderCredentials(username, apiToken, server string) (*DNSProvider,
 }
 
 // Present creates a TXT record to fulfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
 
 	request := &namecom.Record{
 		DomainName: domain,
-		Host:       c.extractRecordName(fqdn, domain),
+		Host:       d.extractRecordName(fqdn, domain),
 		Type:       "TXT",
 		TTL:        uint32(ttl),
 		Answer:     value,
 	}
 
-	_, err := c.client.CreateRecord(request)
+	_, err := d.client.CreateRecord(request)
 	if err != nil {
 		return fmt.Errorf("Name.com API call failed: %v", err)
 	}
@@ -69,10 +69,10 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 }
 
 // CleanUp removes the TXT record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
 
-	records, err := c.getRecords(domain)
+	records, err := d.getRecords(domain)
 	if err != nil {
 		return err
 	}
@@ -83,7 +83,7 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 				DomainName: domain,
 				ID:         rec.ID,
 			}
-			_, err := c.client.DeleteRecord(request)
+			_, err := d.client.DeleteRecord(request)
 			if err != nil {
 				return err
 			}
@@ -93,7 +93,7 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	return nil
 }
 
-func (c *DNSProvider) getRecords(domain string) ([]*namecom.Record, error) {
+func (d *DNSProvider) getRecords(domain string) ([]*namecom.Record, error) {
 	var (
 		err      error
 		records  []*namecom.Record
@@ -106,7 +106,7 @@ func (c *DNSProvider) getRecords(domain string) ([]*namecom.Record, error) {
 	}
 
 	for request.Page > 0 {
-		response, err = c.client.ListRecords(request)
+		response, err = d.client.ListRecords(request)
 		if err != nil {
 			return nil, err
 		}
@@ -118,7 +118,7 @@ func (c *DNSProvider) getRecords(domain string) ([]*namecom.Record, error) {
 	return records, nil
 }
 
-func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
+func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
 	name := acme.UnFqdn(fqdn)
 	if idx := strings.Index(name, "."+domain); idx != -1 {
 		return name[:idx]
diff --git a/providers/dns/ns1/ns1.go b/providers/dns/ns1/ns1.go
index e41af869..d37da4cd 100644
--- a/providers/dns/ns1/ns1.go
+++ b/providers/dns/ns1/ns1.go
@@ -43,16 +43,16 @@ func NewDNSProviderCredentials(key string) (*DNSProvider, error) {
 }
 
 // Present creates a TXT record to fulfil the dns-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
 
-	zone, err := c.getHostedZone(domain)
+	zone, err := d.getHostedZone(domain)
 	if err != nil {
 		return err
 	}
 
-	record := c.newTxtRecord(zone, fqdn, value, ttl)
-	_, err = c.client.Records.Create(record)
+	record := d.newTxtRecord(zone, fqdn, value, ttl)
+	_, err = d.client.Records.Create(record)
 	if err != nil && err != rest.ErrRecordExists {
 		return err
 	}
@@ -61,21 +61,21 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 }
 
 // CleanUp removes the TXT record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
 
-	zone, err := c.getHostedZone(domain)
+	zone, err := d.getHostedZone(domain)
 	if err != nil {
 		return err
 	}
 
 	name := acme.UnFqdn(fqdn)
-	_, err = c.client.Records.Delete(zone.Zone, name, "TXT")
+	_, err = d.client.Records.Delete(zone.Zone, name, "TXT")
 	return err
 }
 
-func (c *DNSProvider) getHostedZone(domain string) (*dns.Zone, error) {
-	zone, _, err := c.client.Zones.Get(domain)
+func (d *DNSProvider) getHostedZone(domain string) (*dns.Zone, error) {
+	zone, _, err := d.client.Zones.Get(domain)
 	if err != nil {
 		return nil, err
 	}
@@ -83,7 +83,7 @@ func (c *DNSProvider) getHostedZone(domain string) (*dns.Zone, error) {
 	return zone, nil
 }
 
-func (c *DNSProvider) newTxtRecord(zone *dns.Zone, fqdn, value string, ttl int) *dns.Record {
+func (d *DNSProvider) newTxtRecord(zone *dns.Zone, fqdn, value string, ttl int) *dns.Record {
 	name := acme.UnFqdn(fqdn)
 
 	return &dns.Record{
diff --git a/providers/dns/otc/mock.go b/providers/dns/otc/mock.go
index babc2b3a..127dd5cc 100644
--- a/providers/dns/otc/mock.go
+++ b/providers/dns/otc/mock.go
@@ -77,7 +77,7 @@ func (m *DNSMock) HandleListZonesSuccessfully() {
 		  }]}
 		`)
 
-		assert.Equal(m.t, r.Method, "GET")
+		assert.Equal(m.t, r.Method, http.MethodGet)
 		assert.Equal(m.t, r.URL.Path, "/v2/zones")
 		assert.Equal(m.t, r.URL.RawQuery, "name=example.com.")
 		assert.Equal(m.t, r.Header.Get("Content-Type"), "application/json")
@@ -92,7 +92,7 @@ func (m *DNSMock) HandleListZonesEmpty() {
 		  ]}
 		`)
 
-		assert.Equal(m.t, r.Method, "GET")
+		assert.Equal(m.t, r.Method, http.MethodGet)
 		assert.Equal(m.t, r.URL.Path, "/v2/zones")
 		assert.Equal(m.t, r.URL.RawQuery, "name=example.com.")
 		assert.Equal(m.t, r.Header.Get("Content-Type"), "application/json")
@@ -108,7 +108,7 @@ func (m *DNSMock) HandleDeleteRecordsetsSuccessfully() {
 		  }]}
 		`)
 
-		assert.Equal(m.t, r.Method, "DELETE")
+		assert.Equal(m.t, r.Method, http.MethodDelete)
 		assert.Equal(m.t, r.URL.Path, "/v2/zones/123123/recordsets/321321")
 		assert.Equal(m.t, r.Header.Get("Content-Type"), "application/json")
 	})
@@ -130,7 +130,7 @@ func (m *DNSMock) HandleListRecordsetsEmpty() {
 // HandleListRecordsetsSuccessfully Handle list recordsets successfully
 func (m *DNSMock) HandleListRecordsetsSuccessfully() {
 	m.Mux.HandleFunc("/v2/zones/123123/recordsets", func(w http.ResponseWriter, r *http.Request) {
-		if r.Method == "GET" {
+		if r.Method == http.MethodGet {
 			fmt.Fprintf(w, `{
 			  "recordsets":[{
 			    "id":"321321"
@@ -140,7 +140,7 @@ func (m *DNSMock) HandleListRecordsetsSuccessfully() {
 			assert.Equal(m.t, r.URL.Path, "/v2/zones/123123/recordsets")
 			assert.Equal(m.t, r.URL.RawQuery, "type=TXT&name=_acme-challenge.example.com.")
 
-		} else if r.Method == "POST" {
+		} else if r.Method == http.MethodPost {
 			body, err := ioutil.ReadAll(r.Body)
 
 			assert.Nil(m.t, err)
diff --git a/providers/dns/otc/otc.go b/providers/dns/otc/otc.go
index 76941c8d..30535f7e 100644
--- a/providers/dns/otc/otc.go
+++ b/providers/dns/otc/otc.go
@@ -170,7 +170,7 @@ func (d *DNSProvider) loginRequest() error {
 	if err != nil {
 		return err
 	}
-	req, err := http.NewRequest("POST", d.identityEndpoint, bytes.NewReader(body))
+	req, err := http.NewRequest(http.MethodPost, d.identityEndpoint, bytes.NewReader(body))
 	if err != nil {
 		return err
 	}
@@ -242,7 +242,7 @@ func (d *DNSProvider) getZoneID(zone string) (string, error) {
 	}
 
 	resource := fmt.Sprintf("zones?name=%s", zone)
-	resp, err := d.SendRequest("GET", resource, nil)
+	resp, err := d.SendRequest(http.MethodGet, resource, nil)
 	if err != nil {
 		return "", err
 	}
@@ -278,7 +278,7 @@ func (d *DNSProvider) getRecordSetID(zoneID string, fqdn string) (string, error)
 	}
 
 	resource := fmt.Sprintf("zones/%s/recordsets?type=TXT&name=%s", zoneID, fqdn)
-	resp, err := d.SendRequest("GET", resource, nil)
+	resp, err := d.SendRequest(http.MethodGet, resource, nil)
 	if err != nil {
 		return "", err
 	}
@@ -307,7 +307,7 @@ func (d *DNSProvider) getRecordSetID(zoneID string, fqdn string) (string, error)
 func (d *DNSProvider) deleteRecordSet(zoneID, recordID string) error {
 	resource := fmt.Sprintf("zones/%s/recordsets/%s", zoneID, recordID)
 
-	_, err := d.SendRequest("DELETE", resource, nil)
+	_, err := d.SendRequest(http.MethodDelete, resource, nil)
 	return err
 }
 
@@ -351,7 +351,7 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 		TTL:         ttl,
 		Records:     []string{fmt.Sprintf("\"%s\"", value)},
 	}
-	_, err = d.SendRequest("POST", resource, r1)
+	_, err = d.SendRequest(http.MethodPost, resource, r1)
 	return err
 }
 
diff --git a/providers/dns/ovh/ovh.go b/providers/dns/ovh/ovh.go
index 98752306..e1999ea5 100644
--- a/providers/dns/ovh/ovh.go
+++ b/providers/dns/ovh/ovh.go
@@ -102,16 +102,14 @@ func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	// Create TXT record
 	err = d.client.Post(reqURL, reqData, &respData)
 	if err != nil {
-		fmt.Printf("Error when call OVH api to add record : %q \n", err)
-		return err
+		return fmt.Errorf("error when call OVH api to add record: %v", err)
 	}
 
 	// Apply the change
 	reqURL = fmt.Sprintf("/domain/zone/%s/refresh", authZone)
 	err = d.client.Post(reqURL, nil, nil)
 	if err != nil {
-		fmt.Printf("Error when call OVH api to refresh zone : %q \n", err)
-		return err
+		return fmt.Errorf("error when call OVH api to refresh zone: %v", err)
 	}
 
 	d.recordIDsMu.Lock()
@@ -144,8 +142,7 @@ func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 
 	err = d.client.Delete(reqURL, nil)
 	if err != nil {
-		fmt.Printf("Error when call OVH api to delete challenge record : %q \n", err)
-		return err
+		return fmt.Errorf("error when call OVH api to delete challenge record: %v", err)
 	}
 
 	// Delete record ID from map
diff --git a/providers/dns/pdns/pdns.go b/providers/dns/pdns/pdns.go
index e97de9a7..3b9915ac 100644
--- a/providers/dns/pdns/pdns.go
+++ b/providers/dns/pdns/pdns.go
@@ -14,6 +14,7 @@ import (
 	"time"
 
 	"github.com/xenolf/lego/acme"
+	"github.com/xenolf/lego/log"
 	"github.com/xenolf/lego/platform/config/env"
 )
 
@@ -22,6 +23,7 @@ type DNSProvider struct {
 	apiKey     string
 	host       *url.URL
 	apiVersion int
+	client     *http.Client
 }
 
 // NewDNSProvider returns a DNSProvider instance configured for pdns.
@@ -52,25 +54,31 @@ func NewDNSProviderCredentials(host *url.URL, key string) (*DNSProvider, error)
 		return nil, fmt.Errorf("PDNS API URL missing")
 	}
 
-	provider := &DNSProvider{
+	d := &DNSProvider{
 		host:   host,
 		apiKey: key,
+		client: &http.Client{Timeout: 30 * time.Second},
 	}
-	provider.getAPIVersion()
 
-	return provider, nil
+	apiVersion, err := d.getAPIVersion()
+	if err != nil {
+		log.Warnf("PDNS: failed to get API version %v", err)
+	}
+	d.apiVersion = apiVersion
+
+	return d, nil
 }
 
 // Timeout returns the timeout and interval to use when checking for DNS
 // propagation. Adjusting here to cope with spikes in propagation times.
-func (c *DNSProvider) Timeout() (timeout, interval time.Duration) {
+func (d *DNSProvider) Timeout() (timeout, interval time.Duration) {
 	return 120 * time.Second, 2 * time.Second
 }
 
 // Present creates a TXT record to fulfil the dns-01 challenge
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
-	zone, err := c.getHostedZone(fqdn)
+	zone, err := d.getHostedZone(fqdn)
 	if err != nil {
 		return err
 	}
@@ -78,7 +86,7 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 	name := fqdn
 
 	// pre-v1 API wants non-fqdn
-	if c.apiVersion == 0 {
+	if d.apiVersion == 0 {
 		name = acme.UnFqdn(fqdn)
 	}
 
@@ -110,20 +118,20 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 		return err
 	}
 
-	_, err = c.makeRequest("PATCH", zone.URL, bytes.NewReader(body))
+	_, err = d.makeRequest(http.MethodPatch, zone.URL, bytes.NewReader(body))
 	return err
 }
 
 // CleanUp removes the TXT record matching the specified parameters
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
 
-	zone, err := c.getHostedZone(fqdn)
+	zone, err := d.getHostedZone(fqdn)
 	if err != nil {
 		return err
 	}
 
-	set, err := c.findTxtRecord(fqdn)
+	set, err := d.findTxtRecord(fqdn)
 	if err != nil {
 		return err
 	}
@@ -142,11 +150,11 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 		return err
 	}
 
-	_, err = c.makeRequest("PATCH", zone.URL, bytes.NewReader(body))
+	_, err = d.makeRequest(http.MethodPatch, zone.URL, bytes.NewReader(body))
 	return err
 }
 
-func (c *DNSProvider) getHostedZone(fqdn string) (*hostedZone, error) {
+func (d *DNSProvider) getHostedZone(fqdn string) (*hostedZone, error) {
 	var zone hostedZone
 	authZone, err := acme.FindZoneByFqdn(fqdn, acme.RecursiveNameservers)
 	if err != nil {
@@ -154,12 +162,12 @@ func (c *DNSProvider) getHostedZone(fqdn string) (*hostedZone, error) {
 	}
 
 	url := "/servers/localhost/zones"
-	result, err := c.makeRequest("GET", url, nil)
+	result, err := d.makeRequest(http.MethodGet, url, nil)
 	if err != nil {
 		return nil, err
 	}
 
-	zones := []hostedZone{}
+	var zones []hostedZone
 	err = json.Unmarshal(result, &zones)
 	if err != nil {
 		return nil, err
@@ -172,7 +180,7 @@ func (c *DNSProvider) getHostedZone(fqdn string) (*hostedZone, error) {
 		}
 	}
 
-	result, err = c.makeRequest("GET", url, nil)
+	result, err = d.makeRequest(http.MethodGet, url, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -198,13 +206,13 @@ func (c *DNSProvider) getHostedZone(fqdn string) (*hostedZone, error) {
 	return &zone, nil
 }
 
-func (c *DNSProvider) findTxtRecord(fqdn string) (*rrSet, error) {
-	zone, err := c.getHostedZone(fqdn)
+func (d *DNSProvider) findTxtRecord(fqdn string) (*rrSet, error) {
+	zone, err := d.getHostedZone(fqdn)
 	if err != nil {
 		return nil, err
 	}
 
-	_, err = c.makeRequest("GET", zone.URL, nil)
+	_, err = d.makeRequest(http.MethodGet, zone.URL, nil)
 	if err != nil {
 		return nil, err
 	}
@@ -218,21 +226,21 @@ func (c *DNSProvider) findTxtRecord(fqdn string) (*rrSet, error) {
 	return nil, fmt.Errorf("no existing record found for %s", fqdn)
 }
 
-func (c *DNSProvider) getAPIVersion() {
+func (d *DNSProvider) getAPIVersion() (int, error) {
 	type APIVersion struct {
 		URL     string `json:"url"`
 		Version int    `json:"version"`
 	}
 
-	result, err := c.makeRequest("GET", "/api", nil)
+	result, err := d.makeRequest(http.MethodGet, "/api", nil)
 	if err != nil {
-		return
+		return 0, err
 	}
 
 	var versions []APIVersion
 	err = json.Unmarshal(result, &versions)
 	if err != nil {
-		return
+		return 0, err
 	}
 
 	latestVersion := 0
@@ -241,41 +249,45 @@ func (c *DNSProvider) getAPIVersion() {
 			latestVersion = v.Version
 		}
 	}
-	c.apiVersion = latestVersion
+
+	return latestVersion, err
 }
 
-func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
+func (d *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
 	type APIError struct {
 		Error string `json:"error"`
 	}
+
 	var path = ""
-	if c.host.Path != "/" {
-		path = c.host.Path
+	if d.host.Path != "/" {
+		path = d.host.Path
 	}
+
 	if !strings.HasPrefix(uri, "/") {
 		uri = "/" + uri
 	}
-	if c.apiVersion > 0 && !strings.HasPrefix(uri, "/api/v") {
-		uri = "/api/v" + strconv.Itoa(c.apiVersion) + uri
+
+	if d.apiVersion > 0 && !strings.HasPrefix(uri, "/api/v") {
+		uri = "/api/v" + strconv.Itoa(d.apiVersion) + uri
 	}
-	url := c.host.Scheme + "://" + c.host.Host + path + uri
+
+	url := d.host.Scheme + "://" + d.host.Host + path + uri
 	req, err := http.NewRequest(method, url, body)
 	if err != nil {
 		return nil, err
 	}
 
-	req.Header.Set("X-API-Key", c.apiKey)
+	req.Header.Set("X-API-Key", d.apiKey)
 
-	client := http.Client{Timeout: 30 * time.Second}
-	resp, err := client.Do(req)
+	resp, err := d.client.Do(req)
 	if err != nil {
-		return nil, fmt.Errorf("Error talking to PDNS API -> %v", err)
+		return nil, fmt.Errorf("error talking to PDNS API -> %v", err)
 	}
 
 	defer resp.Body.Close()
 
-	if resp.StatusCode != 422 && (resp.StatusCode < 200 || resp.StatusCode >= 300) {
-		return nil, fmt.Errorf("Unexpected HTTP status code %d when fetching '%s'", resp.StatusCode, url)
+	if resp.StatusCode != http.StatusUnprocessableEntity && (resp.StatusCode < 200 || resp.StatusCode >= 300) {
+		return nil, fmt.Errorf("unexpected HTTP status code %d when fetching '%s'", resp.StatusCode, url)
 	}
 
 	var msg json.RawMessage
@@ -297,7 +309,7 @@ func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawM
 			return nil, err
 		}
 		if apiError.Error != "" {
-			return nil, fmt.Errorf("Error talking to PDNS API -> %v", apiError.Error)
+			return nil, fmt.Errorf("error talking to PDNS API -> %v", apiError.Error)
 		}
 	}
 	return msg, nil
diff --git a/providers/dns/rackspace/rackspace.go b/providers/dns/rackspace/rackspace.go
index 1ec576a9..358af69d 100644
--- a/providers/dns/rackspace/rackspace.go
+++ b/providers/dns/rackspace/rackspace.go
@@ -22,6 +22,7 @@ var rackspaceAPIURL = "https://identity.api.rackspacecloud.com/v2.0/tokens"
 type DNSProvider struct {
 	token            string
 	cloudDNSEndpoint string
+	client           *http.Client
 }
 
 // NewDNSProvider returns a DNSProvider instance configured for Rackspace.
@@ -44,35 +45,7 @@ func NewDNSProviderCredentials(user, key string) (*DNSProvider, error) {
 		return nil, fmt.Errorf("Rackspace credentials missing")
 	}
 
-	type APIKeyCredentials struct {
-		Username string `json:"username"`
-		APIKey   string `json:"apiKey"`
-	}
-
-	type Auth struct {
-		APIKeyCredentials `json:"RAX-KSKEY:apiKeyCredentials"`
-	}
-
-	type RackspaceAuthData struct {
-		Auth `json:"auth"`
-	}
-
-	type RackspaceIdentity struct {
-		Access struct {
-			ServiceCatalog []struct {
-				Endpoints []struct {
-					PublicURL string `json:"publicURL"`
-					TenantID  string `json:"tenantId"`
-				} `json:"endpoints"`
-				Name string `json:"name"`
-			} `json:"serviceCatalog"`
-			Token struct {
-				ID string `json:"id"`
-			} `json:"token"`
-		} `json:"access"`
-	}
-
-	authData := RackspaceAuthData{
+	authData := AuthData{
 		Auth: Auth{
 			APIKeyCredentials: APIKeyCredentials{
 				Username: user,
@@ -86,13 +59,13 @@ func NewDNSProviderCredentials(user, key string) (*DNSProvider, error) {
 		return nil, err
 	}
 
-	req, err := http.NewRequest("POST", rackspaceAPIURL, bytes.NewReader(body))
+	req, err := http.NewRequest(http.MethodPost, rackspaceAPIURL, bytes.NewReader(body))
 	if err != nil {
 		return nil, err
 	}
 	req.Header.Set("Content-Type", "application/json")
 
-	client := http.Client{Timeout: 30 * time.Second}
+	client := &http.Client{Timeout: 30 * time.Second}
 	resp, err := client.Do(req)
 	if err != nil {
 		return nil, fmt.Errorf("error querying Rackspace Identity API: %v", err)
@@ -103,7 +76,7 @@ func NewDNSProviderCredentials(user, key string) (*DNSProvider, error) {
 		return nil, fmt.Errorf("Rackspace Authentication failed. Response code: %d", resp.StatusCode)
 	}
 
-	var rackspaceIdentity RackspaceIdentity
+	var rackspaceIdentity Identity
 	err = json.NewDecoder(resp.Body).Decode(&rackspaceIdentity)
 	if err != nil {
 		return nil, err
@@ -124,13 +97,14 @@ func NewDNSProviderCredentials(user, key string) (*DNSProvider, error) {
 	return &DNSProvider{
 		token:            rackspaceIdentity.Access.Token.ID,
 		cloudDNSEndpoint: dnsEndpoint,
+		client:           client,
 	}, nil
 }
 
 // Present creates a TXT record to fulfil the dns-01 challenge
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, _ := acme.DNS01Record(domain, keyAuth)
-	zoneID, err := c.getHostedZoneID(fqdn)
+	zoneID, err := d.getHostedZoneID(fqdn)
 	if err != nil {
 		return err
 	}
@@ -149,30 +123,30 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 		return err
 	}
 
-	_, err = c.makeRequest("POST", fmt.Sprintf("/domains/%d/records", zoneID), bytes.NewReader(body))
+	_, err = d.makeRequest(http.MethodPost, fmt.Sprintf("/domains/%d/records", zoneID), bytes.NewReader(body))
 	return err
 }
 
 // CleanUp removes the TXT record matching the specified parameters
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
-	zoneID, err := c.getHostedZoneID(fqdn)
+	zoneID, err := d.getHostedZoneID(fqdn)
 	if err != nil {
 		return err
 	}
 
-	record, err := c.findTxtRecord(fqdn, zoneID)
+	record, err := d.findTxtRecord(fqdn, zoneID)
 	if err != nil {
 		return err
 	}
 
-	_, err = c.makeRequest("DELETE", fmt.Sprintf("/domains/%d/records?id=%s", zoneID, record.ID), nil)
+	_, err = d.makeRequest(http.MethodDelete, fmt.Sprintf("/domains/%d/records?id=%s", zoneID, record.ID), nil)
 	return err
 }
 
 // getHostedZoneID performs a lookup to get the DNS zone which needs
 // modifying for a given FQDN
-func (c *DNSProvider) getHostedZoneID(fqdn string) (int, error) {
+func (d *DNSProvider) getHostedZoneID(fqdn string) (int, error) {
 	// HostedZones represents the response when querying Rackspace DNS zones
 	type ZoneSearchResponse struct {
 		TotalEntries int `json:"totalEntries"`
@@ -187,7 +161,7 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (int, error) {
 		return 0, err
 	}
 
-	result, err := c.makeRequest("GET", fmt.Sprintf("/domains?name=%s", acme.UnFqdn(authZone)), nil)
+	result, err := d.makeRequest(http.MethodGet, fmt.Sprintf("/domains?name=%s", acme.UnFqdn(authZone)), nil)
 	if err != nil {
 		return 0, err
 	}
@@ -207,8 +181,8 @@ func (c *DNSProvider) getHostedZoneID(fqdn string) (int, error) {
 }
 
 // findTxtRecord searches a DNS zone for a TXT record with a specific name
-func (c *DNSProvider) findTxtRecord(fqdn string, zoneID int) (*Record, error) {
-	result, err := c.makeRequest("GET", fmt.Sprintf("/domains/%d/records?type=TXT&name=%s", zoneID, acme.UnFqdn(fqdn)), nil)
+func (d *DNSProvider) findTxtRecord(fqdn string, zoneID int) (*Record, error) {
+	result, err := d.makeRequest(http.MethodGet, fmt.Sprintf("/domains/%d/records?type=TXT&name=%s", zoneID, acme.UnFqdn(fqdn)), nil)
 	if err != nil {
 		return nil, err
 	}
@@ -232,14 +206,14 @@ func (c *DNSProvider) findTxtRecord(fqdn string, zoneID int) (*Record, error) {
 }
 
 // makeRequest is a wrapper function used for making DNS API requests
-func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
-	url := c.cloudDNSEndpoint + uri
+func (d *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawMessage, error) {
+	url := d.cloudDNSEndpoint + uri
 	req, err := http.NewRequest(method, url, body)
 	if err != nil {
 		return nil, err
 	}
 
-	req.Header.Set("X-Auth-Token", c.token)
+	req.Header.Set("X-Auth-Token", d.token)
 	req.Header.Set("Content-Type", "application/json")
 
 	client := http.Client{Timeout: 30 * time.Second}
@@ -263,6 +237,38 @@ func (c *DNSProvider) makeRequest(method, uri string, body io.Reader) (json.RawM
 	return r, nil
 }
 
+// APIKeyCredentials API credential
+type APIKeyCredentials struct {
+	Username string `json:"username"`
+	APIKey   string `json:"apiKey"`
+}
+
+// Auth auth credentials
+type Auth struct {
+	APIKeyCredentials `json:"RAX-KSKEY:apiKeyCredentials"`
+}
+
+// AuthData Auth data
+type AuthData struct {
+	Auth `json:"auth"`
+}
+
+// Identity  Identity
+type Identity struct {
+	Access struct {
+		ServiceCatalog []struct {
+			Endpoints []struct {
+				PublicURL string `json:"publicURL"`
+				TenantID  string `json:"tenantId"`
+			} `json:"endpoints"`
+			Name string `json:"name"`
+		} `json:"serviceCatalog"`
+		Token struct {
+			ID string `json:"id"`
+		} `json:"token"`
+	} `json:"access"`
+}
+
 // Records is the list of records sent/received from the DNS API
 type Records struct {
 	Record []Record `json:"records"`
diff --git a/providers/dns/vultr/vultr.go b/providers/dns/vultr/vultr.go
index 5694e292..27cfa524 100644
--- a/providers/dns/vultr/vultr.go
+++ b/providers/dns/vultr/vultr.go
@@ -35,25 +35,21 @@ func NewDNSProviderCredentials(apiKey string) (*DNSProvider, error) {
 		return nil, fmt.Errorf("Vultr credentials missing")
 	}
 
-	c := &DNSProvider{
-		client: vultr.NewClient(apiKey, nil),
-	}
-
-	return c, nil
+	return &DNSProvider{client: vultr.NewClient(apiKey, nil)}, nil
 }
 
 // Present creates a TXT record to fulfil the DNS-01 challenge.
-func (c *DNSProvider) Present(domain, token, keyAuth string) error {
+func (d *DNSProvider) Present(domain, token, keyAuth string) error {
 	fqdn, value, ttl := acme.DNS01Record(domain, keyAuth)
 
-	zoneDomain, err := c.getHostedZone(domain)
+	zoneDomain, err := d.getHostedZone(domain)
 	if err != nil {
 		return err
 	}
 
-	name := c.extractRecordName(fqdn, zoneDomain)
+	name := d.extractRecordName(fqdn, zoneDomain)
 
-	err = c.client.CreateDNSRecord(zoneDomain, name, "TXT", `"`+value+`"`, 0, ttl)
+	err = d.client.CreateDNSRecord(zoneDomain, name, "TXT", `"`+value+`"`, 0, ttl)
 	if err != nil {
 		return fmt.Errorf("Vultr API call failed: %v", err)
 	}
@@ -62,16 +58,16 @@ func (c *DNSProvider) Present(domain, token, keyAuth string) error {
 }
 
 // CleanUp removes the TXT record matching the specified parameters.
-func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
+func (d *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	fqdn, _, _ := acme.DNS01Record(domain, keyAuth)
 
-	zoneDomain, records, err := c.findTxtRecords(domain, fqdn)
+	zoneDomain, records, err := d.findTxtRecords(domain, fqdn)
 	if err != nil {
 		return err
 	}
 
 	for _, rec := range records {
-		err := c.client.DeleteDNSRecord(zoneDomain, rec.RecordID)
+		err := d.client.DeleteDNSRecord(zoneDomain, rec.RecordID)
 		if err != nil {
 			return err
 		}
@@ -79,17 +75,17 @@ func (c *DNSProvider) CleanUp(domain, token, keyAuth string) error {
 	return nil
 }
 
-func (c *DNSProvider) getHostedZone(domain string) (string, error) {
-	domains, err := c.client.GetDNSDomains()
+func (d *DNSProvider) getHostedZone(domain string) (string, error) {
+	domains, err := d.client.GetDNSDomains()
 	if err != nil {
 		return "", fmt.Errorf("Vultr API call failed: %v", err)
 	}
 
 	var hostedDomain vultr.DNSDomain
-	for _, d := range domains {
-		if strings.HasSuffix(domain, d.Domain) {
-			if len(d.Domain) > len(hostedDomain.Domain) {
-				hostedDomain = d
+	for _, dom := range domains {
+		if strings.HasSuffix(domain, dom.Domain) {
+			if len(dom.Domain) > len(hostedDomain.Domain) {
+				hostedDomain = dom
 			}
 		}
 	}
@@ -100,19 +96,19 @@ func (c *DNSProvider) getHostedZone(domain string) (string, error) {
 	return hostedDomain.Domain, nil
 }
 
-func (c *DNSProvider) findTxtRecords(domain, fqdn string) (string, []vultr.DNSRecord, error) {
-	zoneDomain, err := c.getHostedZone(domain)
+func (d *DNSProvider) findTxtRecords(domain, fqdn string) (string, []vultr.DNSRecord, error) {
+	zoneDomain, err := d.getHostedZone(domain)
 	if err != nil {
 		return "", nil, err
 	}
 
 	var records []vultr.DNSRecord
-	result, err := c.client.GetDNSRecords(zoneDomain)
+	result, err := d.client.GetDNSRecords(zoneDomain)
 	if err != nil {
 		return "", records, fmt.Errorf("Vultr API call has failed: %v", err)
 	}
 
-	recordName := c.extractRecordName(fqdn, zoneDomain)
+	recordName := d.extractRecordName(fqdn, zoneDomain)
 	for _, record := range result {
 		if record.Type == "TXT" && record.Name == recordName {
 			records = append(records, record)
@@ -122,7 +118,7 @@ func (c *DNSProvider) findTxtRecords(domain, fqdn string) (string, []vultr.DNSRe
 	return zoneDomain, records, nil
 }
 
-func (c *DNSProvider) extractRecordName(fqdn, domain string) string {
+func (d *DNSProvider) extractRecordName(fqdn, domain string) string {
 	name := acme.UnFqdn(fqdn)
 	if idx := strings.Index(name, "."+domain); idx != -1 {
 		return name[:idx]


Test patch:
diff --git a/acme/client_test.go b/acme/client_test.go
index b37d1bdf..a84b6f30 100644
--- a/acme/client_test.go
+++ b/acme/client_test.go
@@ -152,13 +152,13 @@ func TestValidate(t *testing.T) {
 		w.Header().Add("Replay-Nonce", "12345")
 		w.Header().Add("Retry-After", "0")
 		switch r.Method {
-		case "HEAD":
-		case "POST":
+		case http.MethodHead:
+		case http.MethodPost:
 			st := statuses[0]
 			statuses = statuses[1:]
 			writeJSONResponse(w, &challenge{Type: "http-01", Status: st, URL: "http://example.com/", Token: "token"})
 
-		case "GET":
+		case http.MethodGet:
 			st := statuses[0]
 			statuses = statuses[1:]
 			writeJSONResponse(w, &challenge{Type: "http-01", Status: st, URL: "http://example.com/", Token: "token"})
@@ -199,7 +199,7 @@ func TestGetChallenges(t *testing.T) {
 	var ts *httptest.Server
 	ts = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		switch r.Method {
-		case "GET", "HEAD":
+		case http.MethodGet, http.MethodHead:
 			w.Header().Add("Replay-Nonce", "12345")
 			w.Header().Add("Retry-After", "0")
 			writeJSONResponse(w, directory{
@@ -209,7 +209,7 @@ func TestGetChallenges(t *testing.T) {
 				RevokeCertURL: ts.URL,
 				KeyChangeURL:  ts.URL,
 			})
-		case "POST":
+		case http.MethodPost:
 			writeJSONResponse(w, orderMessage{})
 		}
 	}))
diff --git a/acme/http_test.go b/acme/http_test.go
index 9b88e8a7..370e1245 100644
--- a/acme/http_test.go
+++ b/acme/http_test.go
@@ -22,7 +22,7 @@ func TestHTTPHeadUserAgent(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	if method != "HEAD" {
+	if method != http.MethodHead {
 		t.Errorf("Expected method to be HEAD, got %s", method)
 	}
 	if !strings.Contains(ua, ourUserAgent) {
@@ -44,7 +44,7 @@ func TestHTTPGetUserAgent(t *testing.T) {
 	}
 	res.Body.Close()
 
-	if method != "GET" {
+	if method != http.MethodGet {
 		t.Errorf("Expected method to be GET, got %s", method)
 	}
 	if !strings.Contains(ua, ourUserAgent) {
@@ -66,7 +66,7 @@ func TestHTTPPostUserAgent(t *testing.T) {
 	}
 	res.Body.Close()
 
-	if method != "POST" {
+	if method != http.MethodPost {
 		t.Errorf("Expected method to be POST, got %s", method)
 	}
 	if !strings.Contains(ua, ourUserAgent) {
diff --git a/providers/dns/auroradns/auroradns_test.go b/providers/dns/auroradns/auroradns_test.go
index d8ffd82b..2c41ccbd 100644
--- a/providers/dns/auroradns/auroradns_test.go
+++ b/providers/dns/auroradns/auroradns_test.go
@@ -18,7 +18,7 @@ func TestAuroraDNSPresent(t *testing.T) {
 	var requestReceived bool
 
 	mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		if r.Method == "GET" && r.URL.Path == "/zones" {
+		if r.Method == http.MethodGet && r.URL.Path == "/zones" {
 			w.WriteHeader(http.StatusCreated)
 			fmt.Fprintf(w, `[{
 			        "id":   "c56a4180-65aa-42ec-a945-5fd21dec0538",
@@ -62,7 +62,7 @@ func TestAuroraDNSCleanUp(t *testing.T) {
 	var requestReceived bool
 
 	mock := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		if r.Method == "GET" && r.URL.Path == "/zones" {
+		if r.Method == http.MethodGet && r.URL.Path == "/zones" {
 			w.WriteHeader(http.StatusCreated)
 			fmt.Fprintf(w, `[{
 			        "id":   "c56a4180-65aa-42ec-a945-5fd21dec0538",
@@ -71,7 +71,7 @@ func TestAuroraDNSCleanUp(t *testing.T) {
 			return
 		}
 
-		if r.Method == "POST" && r.URL.Path == "/zones/c56a4180-65aa-42ec-a945-5fd21dec0538/records" {
+		if r.Method == http.MethodPost && r.URL.Path == "/zones/c56a4180-65aa-42ec-a945-5fd21dec0538/records" {
 			w.WriteHeader(http.StatusCreated)
 			fmt.Fprintf(w, `{
 			        "id":   "ec56a4180-65aa-42ec-a945-5fd21dec0538",
diff --git a/providers/dns/linode/linode_test.go b/providers/dns/linode/linode_test.go
index 515cdc25..4fa287fb 100644
--- a/providers/dns/linode/linode_test.go
+++ b/providers/dns/linode/linode_test.go
@@ -127,7 +127,7 @@ func TestDNSProvider_Present(t *testing.T) {
 	mockSrv := newMockServer(t, mockResponses)
 	defer mockSrv.Close()
 
-	p.linode.ToLinode().SetEndpoint(mockSrv.URL)
+	p.client.ToLinode().SetEndpoint(mockSrv.URL)
 
 	err = p.Present(domain, "", keyAuth)
 	assert.NoError(t, err)
@@ -156,7 +156,7 @@ func TestDNSProvider_PresentNoDomain(t *testing.T) {
 	mockSrv := newMockServer(t, mockResponses)
 	defer mockSrv.Close()
 
-	p.linode.ToLinode().SetEndpoint(mockSrv.URL)
+	p.client.ToLinode().SetEndpoint(mockSrv.URL)
 
 	err = p.Present(domain, "", keyAuth)
 	assert.EqualError(t, err, "dns: requested domain not found")
@@ -193,7 +193,7 @@ func TestDNSProvider_PresentCreateFailed(t *testing.T) {
 	mockSrv := newMockServer(t, mockResponses)
 	defer mockSrv.Close()
 
-	p.linode.ToLinode().SetEndpoint(mockSrv.URL)
+	p.client.ToLinode().SetEndpoint(mockSrv.URL)
 
 	err = p.Present(domain, "", keyAuth)
 	assert.EqualError(t, err, "Failed to create domain resource")
@@ -244,7 +244,7 @@ func TestDNSProvider_CleanUp(t *testing.T) {
 	mockSrv := newMockServer(t, mockResponses)
 	defer mockSrv.Close()
 
-	p.linode.ToLinode().SetEndpoint(mockSrv.URL)
+	p.client.ToLinode().SetEndpoint(mockSrv.URL)
 
 	err = p.CleanUp(domain, "", keyAuth)
 	assert.NoError(t, err)
@@ -273,7 +273,7 @@ func TestDNSProvider_CleanUpNoDomain(t *testing.T) {
 	mockSrv := newMockServer(t, mockResponses)
 	defer mockSrv.Close()
 
-	p.linode.ToLinode().SetEndpoint(mockSrv.URL)
+	p.client.ToLinode().SetEndpoint(mockSrv.URL)
 
 	err = p.CleanUp(domain, "", keyAuth)
 	assert.EqualError(t, err, "dns: requested domain not found")
@@ -322,7 +322,7 @@ func TestDNSProvider_CleanUpDeleteFailed(t *testing.T) {
 	mockSrv := newMockServer(t, mockResponses)
 	defer mockSrv.Close()
 
-	p.linode.ToLinode().SetEndpoint(mockSrv.URL)
+	p.client.ToLinode().SetEndpoint(mockSrv.URL)
 
 	err = p.CleanUp(domain, "", keyAuth)
 	assert.EqualError(t, err, "Failed to delete domain resource")
diff --git a/providers/dns/namecheap/namecheap_test.go b/providers/dns/namecheap/namecheap_test.go
index dfa07524..a213cf72 100644
--- a/providers/dns/namecheap/namecheap_test.go
+++ b/providers/dns/namecheap/namecheap_test.go
@@ -6,6 +6,7 @@ import (
 	"net/http/httptest"
 	"net/url"
 	"testing"
+	"time"
 )
 
 var (
@@ -44,7 +45,7 @@ func assertHdr(tc *testcase, t *testing.T, values *url.Values) {
 func mockServer(tc *testcase, t *testing.T, w http.ResponseWriter, r *http.Request) {
 	switch r.Method {
 
-	case "GET":
+	case http.MethodGet:
 		values := r.URL.Query()
 		cmd := values.Get("Command")
 		switch cmd {
@@ -59,7 +60,7 @@ func mockServer(tc *testcase, t *testing.T, w http.ResponseWriter, r *http.Reque
 			t.Errorf("Unexpected GET command: %s", cmd)
 		}
 
-	case "POST":
+	case http.MethodPost:
 		r.ParseForm()
 		values := r.Form
 		cmd := values.Get("Command")
@@ -90,6 +91,7 @@ func testGetHosts(tc *testcase, t *testing.T) {
 		apiUser:  fakeUser,
 		apiKey:   fakeKey,
 		clientIP: fakeClientIP,
+		client:   &http.Client{Timeout: 60 * time.Second},
 	}
 
 	ch, _ := newChallenge(tc.domain, "", tlds)
@@ -133,6 +135,7 @@ func mockDNSProvider(url string) *DNSProvider {
 		apiUser:  fakeUser,
 		apiKey:   fakeKey,
 		clientIP: fakeClientIP,
+		client:   &http.Client{Timeout: 60 * time.Second},
 	}
 }