goinwx.go raw
1 package goinwx
2
3 import (
4 "net/url"
5
6 "github.com/kolo/xmlrpc"
7 )
8
9 // API information.
10 const (
11 APIBaseURL = "https://api.domrobot.com/xmlrpc/"
12 APISandboxBaseURL = "https://api.ote.domrobot.com/xmlrpc/"
13 APILanguage = "en"
14 )
15
16 // Client manages communication with INWX API.
17 type Client struct {
18 // HTTP client used to communicate with the INWX API.
19 RPCClient *xmlrpc.Client
20
21 // API username and password
22 username string
23 password string
24
25 lang string
26
27 common service // Reuse a single struct instead of allocating one for each service on the heap.
28
29 // Services used for communicating with the API
30 Account *AccountService
31 Contacts *ContactService
32 Dnssec *DNSSecService
33 Domains *DomainService
34 Nameservers *NameserverService
35 }
36
37 type service struct {
38 client *Client
39 }
40
41 // ClientOptions Options of the API client.
42 type ClientOptions struct {
43 Sandbox bool
44
45 // Language of the return message. (en/de/es)
46 Lang string
47
48 // Base URL for API requests (only for client testing purpose).
49 BaseURL *url.URL
50 }
51
52 // Request The representation of an API request.
53 type Request struct {
54 ServiceMethod string
55 Args map[string]any
56 }
57
58 // NewClient returns a new INWX API client.
59 func NewClient(username, password string, opts *ClientOptions) *Client {
60 baseURL := getBaseURL(opts).String()
61
62 rpcClient, _ := xmlrpc.NewClient(baseURL, nil)
63
64 client := &Client{
65 RPCClient: rpcClient,
66 username: username,
67 password: password,
68 lang: APILanguage,
69 }
70
71 if opts != nil && opts.Lang != "" {
72 client.lang = opts.Lang
73 }
74
75 client.common.client = client
76 client.Account = (*AccountService)(&client.common)
77 client.Contacts = (*ContactService)(&client.common)
78 client.Dnssec = (*DNSSecService)(&client.common)
79 client.Domains = (*DomainService)(&client.common)
80 client.Nameservers = (*NameserverService)(&client.common)
81
82 return client
83 }
84
85 // NewRequest creates an API request.
86 func (c *Client) NewRequest(serviceMethod string, args map[string]any) *Request {
87 if args != nil {
88 args["lang"] = APILanguage
89 }
90
91 return &Request{ServiceMethod: serviceMethod, Args: args}
92 }
93
94 // Do sends an API request and returns the API response.
95 func (c *Client) Do(req *Request) (map[string]any, error) {
96 var resp Response
97
98 err := c.RPCClient.Call(req.ServiceMethod, req.Args, &resp)
99 if err != nil {
100 return nil, err
101 }
102
103 return resp.ResponseData, checkResponse(&resp)
104 }
105
106 // checkResponse checks the API response for errors, and returns them if present.
107 func checkResponse(r *Response) error {
108 if c := r.Code; c >= 1000 && c <= 1500 {
109 return nil
110 }
111
112 return &ErrorResponse{Code: r.Code, Message: r.Message, Reason: r.Reason, ReasonCode: r.ReasonCode}
113 }
114
115 func getBaseURL(opts *ClientOptions) *url.URL {
116 var useSandbox bool
117 if opts != nil {
118 useSandbox = opts.Sandbox
119 }
120
121 var baseURL *url.URL
122
123 if useSandbox {
124 baseURL, _ = url.Parse(APISandboxBaseURL)
125 } else {
126 baseURL, _ = url.Parse(APIBaseURL)
127 }
128
129 if opts != nil && opts.BaseURL != nil {
130 baseURL = opts.BaseURL
131 }
132
133 return baseURL
134 }
135