client.go raw

   1  package regfishapi
   2  
   3  import (
   4  	"bytes"
   5  	"encoding/json"
   6  	"fmt"
   7  	"io"
   8  	"net/http"
   9  )
  10  
  11  // Client struct holds the API client configuration
  12  // including the base URL and the API key for authentication.
  13  type Client struct {
  14  	BaseURL string
  15  	APIKey  string
  16  	Client  *http.Client
  17  }
  18  
  19  // NewClient creates a new instance of the Regfish API client.
  20  func NewClient(apiKey string) *Client {
  21  	return &Client{
  22  		BaseURL: "https://api.regfish.de",
  23  		APIKey:  apiKey,
  24  		Client:  &http.Client{},
  25  	}
  26  }
  27  
  28  // Request helper for making HTTP requests.
  29  func (c *Client) Request(method, endpoint string, body interface{}, headers map[string]string) ([]byte, error) {
  30  	url := fmt.Sprintf("%s%s", c.BaseURL, endpoint)
  31  
  32  	// Marshal body if provided
  33  	var reqBody []byte
  34  	var err error
  35  	if body != nil {
  36  		reqBody, err = json.Marshal(body)
  37  		if err != nil {
  38  			return nil, fmt.Errorf("failed to marshal body: %w", err)
  39  		}
  40  	}
  41  
  42  	req, err := http.NewRequest(method, url, bytes.NewBuffer(reqBody))
  43  	if err != nil {
  44  		return nil, fmt.Errorf("failed to create request: %w", err)
  45  	}
  46  
  47  	req.Header.Set("x-api-key", c.APIKey)
  48  	req.Header.Set("Content-Type", "application/json")
  49  	for k, v := range headers {
  50  		req.Header.Set(k, v)
  51  	}
  52  
  53  	resp, err := c.Client.Do(req)
  54  	if err != nil {
  55  		return nil, fmt.Errorf("failed to make request: %w", err)
  56  	}
  57  	defer resp.Body.Close()
  58  
  59  	if resp.StatusCode >= 400 {
  60  		return nil, fmt.Errorf("request failed with status code %d", resp.StatusCode)
  61  	}
  62  
  63  	respBody, err := io.ReadAll(resp.Body)
  64  	if err != nil {
  65  		return nil, fmt.Errorf("failed to read response body: %w", err)
  66  	}
  67  
  68  	return respBody, nil
  69  }
  70  
  71  // Record represents a DNS record with common fields.
  72  type Record struct {
  73  	ID         int     `json:"id"`
  74  	Name       string  `json:"name"`
  75  	Type       string  `json:"type"`
  76  	Data       string  `json:"data"`
  77  	TTL        int     `json:"ttl,omitempty"`
  78  	Priority   *int    `json:"priority,omitempty"`
  79  	Annotation *string `json:"annotation,omitempty"`
  80  	Tag        *string `json:"tag,omitempty"`
  81  	Flags      *int    `json:"flags,omitempty"`
  82  }
  83  
  84  // GetRecord retrieves details about a specific DNS record by RRID.
  85  func (c *Client) GetRecord(rrid int) (Record, error) {
  86  	endpoint := fmt.Sprintf("/dns/rr/%d", rrid)
  87  	respBody, err := c.Request("GET", endpoint, nil, nil)
  88  	if err != nil {
  89  		return Record{}, err
  90  	}
  91  
  92  	var response struct {
  93  		Response Record `json:"response"`
  94  	}
  95  
  96  	err = json.Unmarshal(respBody, &response)
  97  	if err != nil {
  98  		return Record{}, fmt.Errorf("failed to unmarshal response: %w", err)
  99  	}
 100  
 101  	return response.Response, nil
 102  }
 103  
 104  // CreateRecord creates a new DNS record.
 105  func (c *Client) CreateRecord(record Record) (Record, error) {
 106  	respBody, err := c.Request("POST", "/dns/rr", record, nil)
 107  	if err != nil {
 108  		return Record{}, err
 109  	}
 110  
 111  	var response struct {
 112  		Response Record `json:"response"`
 113  	}
 114  
 115  	err = json.Unmarshal(respBody, &response)
 116  	if err != nil {
 117  		return Record{}, fmt.Errorf("failed to unmarshal response: %w", err)
 118  	}
 119  
 120  	return response.Response, nil
 121  }
 122  
 123  // UpdateRecord updates a DNS record by the records' name
 124  func (c *Client) UpdateRecord(record Record) (Record, error) {
 125  	endpoint := fmt.Sprintf("/dns/rr")
 126  	respBody, err := c.Request("PATCH", endpoint, record, nil)
 127  	if err != nil {
 128  		return Record{}, err
 129  	}
 130  
 131  	var response struct {
 132  		Response Record `json:"response"`
 133  	}
 134  
 135  	err = json.Unmarshal(respBody, &response)
 136  	if err != nil {
 137  		return Record{}, fmt.Errorf("failed to unmarshal response: %w", err)
 138  	}
 139  
 140  	return response.Response, nil
 141  }
 142  
 143  // UpdateRecordById updates a DNS record by RRID.
 144  func (c *Client) UpdateRecordById(rrid int, record Record) (Record, error) {
 145  	endpoint := fmt.Sprintf("/dns/rr/%d", rrid)
 146  	respBody, err := c.Request("PATCH", endpoint, record, nil)
 147  	if err != nil {
 148  		return Record{}, err
 149  	}
 150  
 151  	var response struct {
 152  		Response Record `json:"response"`
 153  	}
 154  
 155  	err = json.Unmarshal(respBody, &response)
 156  	if err != nil {
 157  		return Record{}, fmt.Errorf("failed to unmarshal response: %w", err)
 158  	}
 159  
 160  	return response.Response, nil
 161  }
 162  
 163  // DeleteRecord deletes a DNS record by RRID.
 164  func (c *Client) DeleteRecord(rrid int) error {
 165  	endpoint := fmt.Sprintf("/dns/rr/%d", rrid)
 166  	_, err := c.Request("DELETE", endpoint, nil, nil)
 167  	return err
 168  }
 169  
 170  // GetRecordsByDomain retrieves all DNS records for a given domain.
 171  func (c *Client) GetRecordsByDomain(domain string) ([]Record, error) {
 172  	endpoint := fmt.Sprintf("/dns/%s/rr", domain)
 173  	respBody, err := c.Request("GET", endpoint, nil, nil)
 174  	if err != nil {
 175  		return nil, err
 176  	}
 177  
 178  	var response struct {
 179  		Response []Record `json:"response"`
 180  	}
 181  
 182  	err = json.Unmarshal(respBody, &response)
 183  	if err != nil {
 184  		return nil, fmt.Errorf("failed to unmarshal response: %w", err)
 185  	}
 186  
 187  	return response.Response, nil
 188  }
 189