client.go raw

   1  package internal
   2  
   3  import (
   4  	"context"
   5  	"encoding/json"
   6  	"fmt"
   7  	"io"
   8  	"net/http"
   9  	"net/url"
  10  	"time"
  11  
  12  	"github.com/go-acme/lego/v4/challenge/dns01"
  13  	"github.com/go-acme/lego/v4/providers/dns/internal/errutils"
  14  )
  15  
  16  const defaultBaseURL = "https://my.do.de/api"
  17  
  18  // Client the do.de API client.
  19  type Client struct {
  20  	token string
  21  
  22  	baseURL    *url.URL
  23  	HTTPClient *http.Client
  24  }
  25  
  26  // NewClient Creates a new Client.
  27  func NewClient(token string) *Client {
  28  	baseURL, _ := url.Parse(defaultBaseURL)
  29  
  30  	return &Client{
  31  		token:      token,
  32  		baseURL:    baseURL,
  33  		HTTPClient: &http.Client{Timeout: 5 * time.Second},
  34  	}
  35  }
  36  
  37  // UpdateTxtRecord Update the domains TXT record
  38  // To update the TXT record we just need to make one simple get request.
  39  func (c *Client) UpdateTxtRecord(ctx context.Context, fqdn, txt string, clearRecord bool) error {
  40  	endpoint := c.baseURL.JoinPath("letsencrypt")
  41  
  42  	query := endpoint.Query()
  43  	query.Set("token", c.token)
  44  	query.Set("domain", dns01.UnFqdn(fqdn))
  45  
  46  	// api call differs per set/delete
  47  	if clearRecord {
  48  		query.Set("action", "delete")
  49  	} else {
  50  		query.Set("value", txt)
  51  	}
  52  
  53  	endpoint.RawQuery = query.Encode()
  54  
  55  	req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), http.NoBody)
  56  	if err != nil {
  57  		return fmt.Errorf("unable to create request: %w", err)
  58  	}
  59  
  60  	resp, err := c.HTTPClient.Do(req)
  61  	if err != nil {
  62  		return errutils.NewHTTPDoError(req, err)
  63  	}
  64  
  65  	defer func() { _ = resp.Body.Close() }()
  66  
  67  	raw, err := io.ReadAll(resp.Body)
  68  	if err != nil {
  69  		return errutils.NewReadResponseError(req, resp.StatusCode, err)
  70  	}
  71  
  72  	var response apiResponse
  73  
  74  	err = json.Unmarshal(raw, &response)
  75  	if err != nil {
  76  		return errutils.NewUnmarshalError(req, resp.StatusCode, raw, err)
  77  	}
  78  
  79  	body := string(raw)
  80  	if !response.Success {
  81  		return fmt.Errorf("request to change TXT record for do.de returned the following error result (%s); used url [%s]", body, endpoint)
  82  	}
  83  
  84  	return nil
  85  }
  86