Skip to content

Commit 1427945

Browse files
committed
refactor: add generic API request helper functions
1 parent 51baf8d commit 1427945

File tree

3 files changed

+216
-0
lines changed

3 files changed

+216
-0
lines changed

hcloud/client_generic.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package hcloud
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/json"
7+
)
8+
9+
func getRequest[Schema any](ctx context.Context, client *Client, url string) (*Schema, *Response, error) {
10+
req, err := client.NewRequest(ctx, "GET", url, nil)
11+
if err != nil {
12+
return nil, nil, err
13+
}
14+
15+
var respBody Schema
16+
resp, err := client.Do(req, &respBody)
17+
if err != nil {
18+
return nil, resp, err
19+
}
20+
21+
return &respBody, resp, nil
22+
}
23+
24+
func postRequest[Schema any](ctx context.Context, client *Client, url string, reqBody any) (*Schema, *Response, error) {
25+
reqBodyBytes, err := json.Marshal(reqBody)
26+
if err != nil {
27+
return nil, nil, err
28+
}
29+
30+
req, err := client.NewRequest(ctx, "POST", url, bytes.NewReader(reqBodyBytes))
31+
if err != nil {
32+
return nil, nil, err
33+
}
34+
35+
var respBody Schema
36+
resp, err := client.Do(req, &respBody)
37+
if err != nil {
38+
return nil, resp, err
39+
}
40+
41+
return &respBody, resp, nil
42+
}
43+
44+
func putRequest[Schema any](ctx context.Context, client *Client, url string, reqBody any) (*Schema, *Response, error) {
45+
reqBodyBytes, err := json.Marshal(reqBody)
46+
if err != nil {
47+
return nil, nil, err
48+
}
49+
50+
req, err := client.NewRequest(ctx, "PUT", url, bytes.NewReader(reqBodyBytes))
51+
if err != nil {
52+
return nil, nil, err
53+
}
54+
55+
var respBody Schema
56+
resp, err := client.Do(req, &respBody)
57+
if err != nil {
58+
return nil, resp, err
59+
}
60+
61+
return &respBody, resp, nil
62+
}
63+
64+
func deleteRequest[Schema any](ctx context.Context, client *Client, url string) (*Schema, *Response, error) {
65+
req, err := client.NewRequest(ctx, "DELETE", url, nil)
66+
if err != nil {
67+
return nil, nil, err
68+
}
69+
70+
var respBody Schema
71+
resp, err := client.Do(req, &respBody)
72+
if err != nil {
73+
return nil, resp, err
74+
}
75+
76+
return &respBody, resp, nil
77+
}
78+
79+
func deleteRequestNoResult(ctx context.Context, client *Client, url string) (*Response, error) {
80+
req, err := client.NewRequest(ctx, "DELETE", url, nil)
81+
if err != nil {
82+
return nil, err
83+
}
84+
85+
return client.Do(req, nil)
86+
}

hcloud/client_generic_test.go

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package hcloud
2+
3+
import (
4+
"io"
5+
"net/http"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
10+
"github.com/hetznercloud/hcloud-go/v2/hcloud/exp/mockutil"
11+
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
12+
)
13+
14+
func TestGenericRequest(t *testing.T) {
15+
t.Run("get", func(t *testing.T) {
16+
ctx, server, client := makeTestUtils(t)
17+
18+
server.Expect([]mockutil.Request{
19+
{
20+
Method: "GET", Path: "/resource",
21+
Status: 200,
22+
JSON: schema.ActionGetResponse{Action: schema.Action{ID: 1234}},
23+
},
24+
})
25+
26+
respBody, resp, err := getRequest[schema.ActionGetResponse](ctx, client, "/resource")
27+
require.NoError(t, err)
28+
require.NotNil(t, resp)
29+
require.NotNil(t, respBody)
30+
31+
require.Equal(t, int64(1234), respBody.Action.ID)
32+
})
33+
34+
t.Run("post", func(t *testing.T) {
35+
ctx, server, client := makeTestUtils(t)
36+
37+
server.Expect([]mockutil.Request{
38+
{
39+
Method: "POST", Path: "/resource",
40+
Want: func(t *testing.T, r *http.Request) {
41+
bodyBytes, err := io.ReadAll(r.Body)
42+
require.NoError(t, err)
43+
require.JSONEq(t, `{"hello": "world"}`, string(bodyBytes))
44+
},
45+
Status: 200,
46+
JSON: schema.ActionGetResponse{Action: schema.Action{ID: 1234}},
47+
},
48+
})
49+
50+
respBody, resp, err := postRequest[schema.ActionGetResponse](ctx, client, "/resource", map[string]string{"hello": "world"})
51+
require.NoError(t, err)
52+
require.NotNil(t, resp)
53+
require.NotNil(t, respBody)
54+
55+
require.Equal(t, int64(1234), respBody.Action.ID)
56+
})
57+
58+
t.Run("put", func(t *testing.T) {
59+
ctx, server, client := makeTestUtils(t)
60+
61+
server.Expect([]mockutil.Request{
62+
{
63+
Method: "PUT", Path: "/resource",
64+
Want: func(t *testing.T, r *http.Request) {
65+
bodyBytes, err := io.ReadAll(r.Body)
66+
require.NoError(t, err)
67+
require.JSONEq(t, `{"hello": "world"}`, string(bodyBytes))
68+
},
69+
Status: 200,
70+
JSON: schema.ActionGetResponse{Action: schema.Action{ID: 1234}},
71+
},
72+
})
73+
74+
respBody, resp, err := putRequest[schema.ActionGetResponse](ctx, client, "/resource", map[string]string{"hello": "world"})
75+
require.NoError(t, err)
76+
require.NotNil(t, resp)
77+
require.NotNil(t, respBody)
78+
79+
require.Equal(t, int64(1234), respBody.Action.ID)
80+
})
81+
82+
t.Run("delete", func(t *testing.T) {
83+
ctx, server, client := makeTestUtils(t)
84+
85+
server.Expect([]mockutil.Request{
86+
{
87+
Method: "DELETE", Path: "/resource",
88+
Status: 200,
89+
JSON: schema.ActionGetResponse{Action: schema.Action{ID: 1234}},
90+
},
91+
})
92+
93+
respBody, resp, err := deleteRequest[schema.ActionGetResponse](ctx, client, "/resource")
94+
require.NoError(t, err)
95+
require.NotNil(t, resp)
96+
require.NotNil(t, respBody)
97+
98+
require.Equal(t, int64(1234), respBody.Action.ID)
99+
})
100+
101+
t.Run("delete no result", func(t *testing.T) {
102+
ctx, server, client := makeTestUtils(t)
103+
104+
server.Expect([]mockutil.Request{
105+
{
106+
Method: "DELETE", Path: "/resource",
107+
Status: 204,
108+
},
109+
})
110+
111+
resp, err := deleteRequestNoResult(ctx, client, "/resource")
112+
require.NoError(t, err)
113+
require.NotNil(t, resp)
114+
})
115+
}

hcloud/client_test.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,24 @@ import (
1515
"github.com/stretchr/testify/assert"
1616
"github.com/stretchr/testify/require"
1717

18+
"github.com/hetznercloud/hcloud-go/v2/hcloud/exp/mockutil"
1819
"github.com/hetznercloud/hcloud-go/v2/hcloud/schema"
1920
)
2021

22+
func makeTestUtils(t *testing.T) (context.Context, *mockutil.Server, *Client) {
23+
ctx := context.Background()
24+
25+
server := mockutil.NewServer(t, nil)
26+
27+
client := NewClient(
28+
WithEndpoint(server.URL),
29+
WithRetryOpts(RetryOpts{BackoffFunc: ConstantBackoff(0), MaxRetries: 5}),
30+
WithPollOpts(PollOpts{BackoffFunc: ConstantBackoff(0)}),
31+
)
32+
33+
return ctx, server, client
34+
}
35+
2136
type testEnv struct {
2237
Server *httptest.Server
2338
Mux *http.ServeMux

0 commit comments

Comments
 (0)