client.go raw
1 package internal
2
3 import (
4 "bytes"
5 "context"
6 "errors"
7 "io"
8 "net/http"
9 "net/url"
10 "time"
11
12 "github.com/go-acme/lego/v4/providers/dns/internal/errutils"
13 )
14
15 const defaultBaseURL = "https://dynup.de/acme.php"
16
17 type Client struct {
18 username string
19 password string
20
21 baseURL string
22 HTTPClient *http.Client
23 }
24
25 func NewClient(username, password string) (*Client, error) {
26 if username == "" || password == "" {
27 return nil, errors.New("credentials missing")
28 }
29
30 return &Client{
31 username: username,
32 password: password,
33 baseURL: defaultBaseURL,
34 HTTPClient: &http.Client{Timeout: 10 * time.Second},
35 }, nil
36 }
37
38 func (c *Client) AddTXTRecord(ctx context.Context, zone, hostname, value string) error {
39 baseURL, err := url.Parse(c.baseURL)
40 if err != nil {
41 return err
42 }
43
44 query := baseURL.Query()
45 query.Set("username", c.username)
46 query.Set("password", c.password)
47 query.Set("hostname", zone)
48 query.Set("add_hostname", hostname)
49 query.Set("txt", value)
50 baseURL.RawQuery = query.Encode()
51
52 req, err := http.NewRequestWithContext(ctx, http.MethodGet, baseURL.String(), http.NoBody)
53 if err != nil {
54 return err
55 }
56
57 resp, err := c.HTTPClient.Do(req)
58 if err != nil {
59 return errutils.NewHTTPDoError(req, err)
60 }
61
62 defer func() { _ = resp.Body.Close() }()
63
64 if resp.StatusCode != http.StatusOK {
65 return errutils.NewUnexpectedResponseStatusCodeError(req, resp)
66 }
67
68 raw, err := io.ReadAll(resp.Body)
69 if err != nil {
70 return errutils.NewReadResponseError(req, resp.StatusCode, err)
71 }
72
73 if !bytes.Equal(raw, []byte("success")) {
74 return errors.New(string(raw))
75 }
76
77 return nil
78 }
79