aboutsummaryrefslogtreecommitdiff
path: root/clients/netbox/http.go
diff options
context:
space:
mode:
Diffstat (limited to 'clients/netbox/http.go')
-rw-r--r--clients/netbox/http.go174
1 files changed, 174 insertions, 0 deletions
diff --git a/clients/netbox/http.go b/clients/netbox/http.go
new file mode 100644
index 0000000..21a2b4b
--- /dev/null
+++ b/clients/netbox/http.go
@@ -0,0 +1,174 @@
1package netbox
2
3import (
4 "bytes"
5 "context"
6 "encoding/json"
7 "fmt"
8 "net/http"
9 "net/url"
10)
11
12// NetboxHttpClient is an HTTP client for the Netbox API. It is very
13// low-level and should not be consumed by most clients. Instead use a
14// client implementing NetboxClient.
15type NetboxHttpClient struct {
16 ApiKey string
17 Endpoint url.URL
18}
19
20func MustNewNetboxHttpClient(apiKey, endpoint string) *NetboxHttpClient {
21 u, err := url.Parse(endpoint)
22 if err != nil {
23 panic(err)
24 }
25 return &NetboxHttpClient{apiKey, *u}
26}
27
28func (c *NetboxHttpClient) Do(ctx context.Context, r NetboxRequest, out any) error {
29 u := c.Endpoint // Store a local copy, requests may mutate it
30 req, err := r.BuildRequest(ctx, &u)
31 if err != nil {
32 return err
33 }
34
35 req.Header.Add("Authorization", fmt.Sprintf("Token %s", c.ApiKey))
36
37 res, err := http.DefaultClient.Do(req)
38 if err != nil {
39 return err
40 }
41 defer res.Body.Close()
42
43 if res.StatusCode != http.StatusOK {
44 apiError := &ApiError{Status: res.StatusCode}
45 if err = json.NewDecoder(res.Body).Decode(apiError); err != nil {
46 return fmt.Errorf("Netbox JSON decode error while parsing error with status %d: %w", res.StatusCode, err)
47 }
48 return apiError
49 }
50
51 if out != nil {
52 return json.NewDecoder(res.Body).Decode(out)
53 }
54
55 return nil
56}
57
58type NetboxRequest interface {
59 BuildRequest(context.Context, *url.URL) (*http.Request, error)
60}
61
62type NetboxGraphQLRequest struct {
63 Query string
64}
65
66var _ NetboxRequest = (*NetboxGraphQLRequest)(nil)
67
68func (r *NetboxGraphQLRequest) BuildRequest(ctx context.Context, host *url.URL) (*http.Request, error) {
69 q, err := json.Marshal(map[string]string{"query": r.Query})
70 if err != nil {
71 return nil, err
72 }
73
74 host.Path = "/graphql/"
75
76 req, err := http.NewRequestWithContext(
77 ctx,
78 http.MethodPost,
79 host.String(),
80 bytes.NewBuffer(q),
81 )
82 if err != nil {
83 return nil, err
84 }
85
86 req.Header.Add("Content-Type", "application/json")
87 req.Header.Add("Accept", "application/json")
88
89 return req, nil
90}
91
92type NetboxGetRequest struct {
93 url.Values
94 Path string
95}
96
97var _ NetboxRequest = (*NetboxGetRequest)(nil)
98
99func NewNetboxGetRequest(path string) *NetboxGetRequest {
100 return &NetboxGetRequest{url.Values{}, path}
101}
102
103func (r *NetboxGetRequest) BuildRequest(ctx context.Context, host *url.URL) (*http.Request, error) {
104 host.Path = r.Path
105 host.RawQuery = r.Encode()
106
107 req, err := http.NewRequestWithContext(
108 ctx,
109 http.MethodGet,
110 host.String(),
111 nil,
112 )
113 if err != nil {
114 return nil, err
115 }
116
117 req.Header.Add("Accept", "application/json")
118
119 return req, nil
120}
121
122type NetboxRawGet struct {
123 Url string
124}
125
126var _ NetboxRequest = (*NetboxRawGet)(nil)
127
128func (r *NetboxRawGet) BuildRequest(ctx context.Context, host *url.URL) (*http.Request, error) {
129 req, err := http.NewRequestWithContext(
130 ctx,
131 http.MethodGet,
132 r.Url,
133 nil,
134 )
135 if err != nil {
136 return nil, err
137 }
138
139 req.Header.Add("Accept", "application/json")
140
141 return req, nil
142}
143
144type NetboxJsonRequest struct {
145 Path string
146 Method string
147 Body any
148}
149
150var _ NetboxRequest = (*NetboxJsonRequest)(nil)
151
152func (r *NetboxJsonRequest) BuildRequest(ctx context.Context, host *url.URL) (*http.Request, error) {
153 host.Path = r.Path
154
155 body, err := json.Marshal(r.Body)
156 if err != nil {
157 return nil, err
158 }
159
160 req, err := http.NewRequestWithContext(
161 ctx,
162 r.Method,
163 host.String(),
164 bytes.NewBuffer(body),
165 )
166 if err != nil {
167 return nil, err
168 }
169
170 req.Header.Add("Content-Type", "application/json")
171 req.Header.Add("Accept", "application/json")
172
173 return req, nil
174}