Skip to content

Commit 0d5db74

Browse files
henrybarretogustavosbarreto
authored andcommitted
feat(pkg): standardize errors on internal http client
1 parent 7108cfa commit 0d5db74

File tree

8 files changed

+167
-80
lines changed

8 files changed

+167
-80
lines changed

pkg/api/internalclient/billing.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package internalclient
22

33
import (
44
"context"
5-
"net/http"
5+
"errors"
66

77
"github.com/shellhub-io/shellhub/pkg/models"
88
)
@@ -18,6 +18,8 @@ type billingAPI interface {
1818
BillingEvaluate(ctx context.Context, tenantID string) (*models.BillingEvaluation, int, error)
1919
}
2020

21+
var ErrBillingRequestFailed = errors.New("billing request failed")
22+
2123
func (c *client) BillingReport(ctx context.Context, tenant string, action string) (int, error) {
2224
res, err := c.http.
2325
R().
@@ -26,7 +28,8 @@ func (c *client) BillingReport(ctx context.Context, tenant string, action string
2628
SetQueryParam("action", action).
2729
Post(c.Config.EnterpriseBaseURL + "/internal/billing/report")
2830
if err != nil {
29-
return http.StatusInternalServerError, err
31+
// TODO: It shouldn't return the status code.
32+
return res.StatusCode(), errors.Join(ErrBillingRequestFailed, err)
3033
}
3134

3235
return res.StatusCode(), nil
@@ -42,7 +45,7 @@ func (c *client) BillingEvaluate(ctx context.Context, tenantID string) (*models.
4245
SetResult(&eval).
4346
Post(c.Config.EnterpriseBaseURL + "/internal/billing/evaluate")
4447
if err != nil {
45-
return eval, resp.StatusCode(), err
48+
return nil, resp.StatusCode(), errors.Join(ErrBillingRequestFailed, err)
4649
}
4750

4851
return eval, resp.StatusCode(), nil

pkg/api/internalclient/device.go

Lines changed: 57 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ type deviceAPI interface {
2424
DevicesHeartbeat(ctx context.Context, uid string) error
2525

2626
// Lookup performs a lookup operation based on the provided parameters.
27-
Lookup(ctx context.Context, lookup map[string]string) (string, []error)
27+
Lookup(ctx context.Context, lookup map[string]string) (string, error)
2828

2929
// DeviceLookup performs a lookup operation based on the provided parameters.
3030
DeviceLookup(ctx context.Context, tenantID, name string) (*models.Device, error)
@@ -33,14 +33,17 @@ type deviceAPI interface {
3333
LookupWebEndpoints(ctx context.Context, address string) (*WebEndpoint, error)
3434
}
3535

36+
// ErrDeviceRequestFailed indicates that the device request failed.
37+
var ErrDeviceRequestFailed = errors.New("device request failed")
38+
3639
func (c *client) DevicesOffline(ctx context.Context, uid string) error {
3740
_, err := c.http.
3841
R().
3942
SetContext(ctx).
4043
SetPathParam("uid", uid).
4144
Post(c.Config.APIBaseURL + "/internal/devices/{uid}/offline")
4245
if err != nil {
43-
return err
46+
return errors.Join(ErrDeviceRequestFailed, err)
4447
}
4548

4649
return nil
@@ -50,27 +53,37 @@ func (c *client) DevicesHeartbeat(ctx context.Context, uid string) error {
5053
return c.worker.SubmitToBatch(ctx, worker.TaskPattern("api:heartbeat"), []byte(uid))
5154
}
5255

53-
func (c *client) Lookup(ctx context.Context, lookup map[string]string) (string, []error) {
56+
// ErrLookupFailed indicates that the lookup operation failed.
57+
var ErrLookupFailed = errors.New("lookup failed")
58+
59+
func (c *client) Lookup(ctx context.Context, lookup map[string]string) (string, error) {
5460
var device struct {
5561
UID string `json:"uid"`
5662
}
5763

58-
resp, _ := c.http.
64+
resp, err := c.http.
5965
R().
6066
SetContext(ctx).
6167
SetQueryParams(lookup).
6268
SetResult(&device).
6369
Get(c.Config.APIBaseURL + "/internal/lookup")
70+
if err != nil {
71+
return "", errors.Join(ErrDeviceRequestFailed, err)
72+
}
6473

6574
if resp.StatusCode() != http.StatusOK {
66-
return "", []error{errors.New("lookup failed")}
75+
return "", ErrLookupFailed
6776
}
6877

6978
return device.UID, nil
7079
}
7180

81+
// ErrDeviceLookupFailed indicates that the device lookup operation failed.
82+
var ErrDeviceLookupFailed = errors.New("device lookup failed")
83+
7284
func (c *client) DeviceLookup(ctx context.Context, tenantID, name string) (*models.Device, error) {
7385
device := new(models.Device)
86+
7487
resp, err := c.http.
7588
R().
7689
SetContext(ctx).
@@ -79,33 +92,41 @@ func (c *client) DeviceLookup(ctx context.Context, tenantID, name string) (*mode
7992
SetResult(&device).
8093
Get(c.Config.APIBaseURL + "/internal/device/lookup")
8194
if err != nil {
82-
return nil, ErrConnectionFailed
95+
return nil, errors.Join(ErrDeviceRequestFailed, err)
8396
}
8497

85-
switch resp.StatusCode() {
86-
case http.StatusOK:
87-
return device, nil
88-
case http.StatusNotFound:
89-
return nil, ErrNotFound
90-
case http.StatusForbidden:
91-
return nil, ErrForbidden
92-
default:
93-
return nil, ErrUnknown
98+
if resp.StatusCode() != http.StatusOK {
99+
return nil, ErrDeviceLookupFailed
94100
}
101+
102+
return device, nil
95103
}
96104

105+
// ErrListDevicesFailed indicates that the operation to list devices failed.
106+
var ErrListDevicesFailed = errors.New("list devices failed")
107+
97108
func (c *client) ListDevices(ctx context.Context) ([]models.Device, error) {
98109
list := []models.Device{}
99110

100-
_, err := c.http.
111+
resp, err := c.http.
101112
R().
102113
SetContext(ctx).
103114
SetResult(list).
104115
Get(c.Config.APIBaseURL + "/api/devices")
116+
if err != nil {
117+
return nil, errors.Join(ErrDeviceRequestFailed, err)
118+
}
119+
120+
if resp.StatusCode() != http.StatusOK {
121+
return nil, ErrListDevicesFailed
122+
}
105123

106-
return list, err
124+
return list, nil
107125
}
108126

127+
// ErrGetDeviceFailed indicates that the operation to get a device failed.
128+
var ErrGetDeviceFailed = errors.New("get device failed")
129+
109130
func (c *client) GetDevice(ctx context.Context, uid string) (*models.Device, error) {
110131
device := new(models.Device)
111132
resp, err := c.http.
@@ -114,17 +135,14 @@ func (c *client) GetDevice(ctx context.Context, uid string) (*models.Device, err
114135
SetResult(&device).
115136
Get(c.Config.APIBaseURL + "/api/devices/{uid}")
116137
if err != nil {
117-
return nil, ErrConnectionFailed
138+
return nil, errors.Join(ErrDeviceRequestFailed, err)
118139
}
119140

120-
switch resp.StatusCode() {
121-
case 400:
122-
return nil, ErrNotFound
123-
case 200:
124-
return device, nil
125-
default:
126-
return nil, ErrUnknown
141+
if resp.StatusCode() != http.StatusOK {
142+
return nil, ErrGetDeviceFailed
127143
}
144+
145+
return device, nil
128146
}
129147

130148
type WebEndpoint struct {
@@ -139,26 +157,28 @@ type WebEndpoint struct {
139157
CreatedAt time.Time `json:"time" bson:"time"`
140158
}
141159

160+
var (
161+
// ErrWebEndpointRequestFailed indicates that the web endpoint request failed.
162+
ErrWebEndpointRequestFailed = errors.New("web endpoint request failed")
163+
// ErrWebEndpointForbidden indicates that access to the web endpoint is forbidden.
164+
ErrWebEndpointForbidden = errors.New("web endpoint access forbidden")
165+
)
166+
142167
func (c *client) LookupWebEndpoints(ctx context.Context, address string) (*WebEndpoint, error) {
143-
var tunnel *WebEndpoint
168+
var endpoint *WebEndpoint
144169
resp, err := c.http.
145170
R().
146171
SetContext(ctx).
147172
SetPathParam("address", address).
148-
SetResult(&tunnel).
173+
SetResult(&endpoint).
149174
Get(c.Config.EnterpriseBaseURL + "/internal/web-endpoints/{address}")
150175
if err != nil {
151-
return nil, ErrConnectionFailed
176+
return nil, errors.Join(ErrWebEndpointRequestFailed, err)
152177
}
153178

154-
switch resp.StatusCode() {
155-
case 404:
156-
return nil, ErrNotFound
157-
case 403:
158-
return nil, ErrForbidden
159-
case 200:
160-
return tunnel, nil
161-
default:
162-
return nil, ErrUnknown
179+
if resp.StatusCode() != http.StatusOK {
180+
return nil, ErrWebEndpointForbidden
163181
}
182+
183+
return endpoint, nil
164184
}

pkg/api/internalclient/firewall.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ type firewallAPI interface {
1414
}
1515

1616
var (
17-
ErrFirewallConnection = errors.New("failed to make the request to evaluate the firewall")
18-
ErrFirewallBlock = errors.New("a firewall rule prohibit this connection")
17+
// ErrFirewallEvaluationRequest is returned when the firewall evaluation request fails for any reason.
18+
ErrFirewallEvaluationRequest = errors.New("failed to evaluate the firewall")
19+
// ErrFirewallBlock is returned when a firewall rule prohibits the connection.
20+
ErrFirewallBlock = errors.New("a firewall rule prohibit this connection")
1921
)
2022

2123
func (c *client) FirewallEvaluate(ctx context.Context, lookup map[string]string) error {
@@ -25,7 +27,7 @@ func (c *client) FirewallEvaluate(ctx context.Context, lookup map[string]string)
2527
SetQueryParams(lookup).
2628
Get(c.Config.EnterpriseBaseURL + "/internal/firewall/rules/evaluate")
2729
if err != nil {
28-
return ErrFirewallConnection
30+
return errors.Join(ErrFirewallEvaluationRequest, err)
2931
}
3032

3133
if resp.StatusCode() != http.StatusOK {

pkg/api/internalclient/mocks/internalclient.go

Lines changed: 5 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/api/internalclient/namespace.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package internalclient
22

33
import (
44
"context"
5+
"errors"
56
"net/http"
67

78
"github.com/shellhub-io/shellhub/pkg/models"
@@ -19,6 +20,13 @@ type namespaceAPI interface {
1920
InviteMember(ctx context.Context, tenantID, userID, forwardedHost string) error
2021
}
2122

23+
var (
24+
// ErrNamespaceLookupRequest indicates that the namespace lookup request failed.
25+
ErrNamespaceLookupRequest = errors.New("namespace lookup request failed")
26+
// ErrNamespaceLookupFailed indicates that the namespace lookup operation failed.
27+
ErrNamespaceLookupFailed = errors.New("namespace lookup failed")
28+
)
29+
2230
func (c *client) NamespaceLookup(ctx context.Context, tenant string) (*models.Namespace, error) {
2331
namespace := new(models.Namespace)
2432
res, err := c.http.
@@ -28,11 +36,11 @@ func (c *client) NamespaceLookup(ctx context.Context, tenant string) (*models.Na
2836
SetResult(namespace).
2937
Get(c.Config.APIBaseURL + "/api/namespaces/{tenant}")
3038
if err != nil {
31-
return nil, err
39+
return nil, errors.Join(ErrNamespaceLookupRequest, err)
3240
}
3341

3442
if res.StatusCode() != http.StatusOK {
35-
return nil, err
43+
return nil, ErrNamespaceLookupFailed
3644
}
3745

3846
return namespace, nil

0 commit comments

Comments
 (0)