Skip to content

Commit b2d1f9e

Browse files
Merge pull request #20 from tranhoangvuit/feature/introduce-error-in-funtion-response
feat(break): introduce an error in the function's response
2 parents 81a3a81 + ba613bd commit b2d1f9e

File tree

7 files changed

+333
-211
lines changed

7 files changed

+333
-211
lines changed

bucket.go

Lines changed: 67 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,51 @@
11
package storage_go
22

33
import (
4-
"bytes"
54
"encoding/json"
6-
"io"
75
"net/http"
86
)
97

10-
func (c *Client) ListBuckets() ([]Bucket, BucketResponseError) {
11-
res, err := c.session.Get(c.clientTransport.baseUrl.String() + "/bucket")
8+
// ListBuckets retrieves the details of all Storage buckets within an existing project.
9+
func (c *Client) ListBuckets() ([]Bucket, error) {
10+
bucketsURL := c.clientTransport.baseUrl.String() + "/bucket"
11+
req, err := c.NewRequest(http.MethodGet, bucketsURL, nil)
1212
if err != nil {
13-
panic(err)
13+
return nil, err
1414
}
1515

16-
defer func(Body io.ReadCloser) {
17-
err := Body.Close()
18-
if err != nil {
19-
panic(err)
20-
}
21-
}(res.Body)
22-
23-
body, err := io.ReadAll(res.Body)
16+
var buckets []Bucket
17+
_, err = c.Do(req, &buckets)
2418
if err != nil {
25-
panic(err)
19+
return nil, err
2620
}
2721

28-
var data []Bucket
29-
err = json.Unmarshal(body, &data)
30-
31-
var respError BucketResponseError
32-
err = json.Unmarshal(body, &respError)
33-
34-
return data, respError
22+
return buckets, nil
3523
}
3624

37-
func (c *Client) GetBucket(id string) (Bucket, BucketResponseError) {
38-
res, err := c.session.Get(c.clientTransport.baseUrl.String() + "/bucket/" + id)
25+
// GetBucket retrieves the details of an existing Storage bucket.
26+
func (c *Client) GetBucket(id string) (Bucket, error) {
27+
bucketURL := c.clientTransport.baseUrl.String() + "/bucket/" + id
28+
req, err := c.NewRequest(http.MethodGet, bucketURL, nil)
3929
if err != nil {
40-
panic(err)
30+
return Bucket{}, err
4131
}
4232

43-
body, err := io.ReadAll(res.Body)
44-
var data Bucket
45-
var error_ BucketResponseError
46-
err = json.Unmarshal(body, &data)
47-
err = json.Unmarshal(body, &error_)
33+
var bucket Bucket
34+
_, err = c.Do(req, &bucket)
35+
if err != nil {
36+
return Bucket{}, err
37+
}
4838

49-
return data, error_
39+
return bucket, nil
5040
}
5141

52-
func (c *Client) CreateBucket(id string, options BucketOptions) (Bucket, BucketResponseError) {
42+
// CreateBucket creates a new Storage bucket
43+
// options.public The visibility of the bucket. Public buckets don't require an authorization token to download objects, but still require a valid token for all other operations. By default, buckets are private.
44+
// options.fileSizeLimit The maximum file size in bytes allowed in the bucket. By default, there is no limit.
45+
// options.allowedMimeTypes The list of allowed MIME types. By default, all MIME types are allowed.
46+
// return newly created bucket id
47+
func (c *Client) CreateBucket(id string, options BucketOptions) (Bucket, error) {
48+
createBucketURL := c.clientTransport.baseUrl.String() + "/bucket"
5349
bodyData := map[string]interface{}{
5450
"id": id,
5551
"name": id,
@@ -63,25 +59,28 @@ func (c *Client) CreateBucket(id string, options BucketOptions) (Bucket, BucketR
6359
if len(options.AllowedMimeTypes) > 0 {
6460
bodyData["allowed_mime_types"] = options.AllowedMimeTypes
6561
}
66-
jsonBody, _ := json.Marshal(bodyData)
67-
res, err := c.session.Post(c.clientTransport.baseUrl.String()+"/bucket",
68-
"application/json",
69-
bytes.NewBuffer(jsonBody))
62+
// jsonBody, _ := json.Marshal(bodyData)
63+
req, err := c.NewRequest(http.MethodPost, createBucketURL, &bodyData)
7064
if err != nil {
71-
panic(err)
65+
return Bucket{}, err
7266
}
7367

74-
body, err := io.ReadAll(res.Body)
75-
var data Bucket
76-
var error_ BucketResponseError
77-
err = json.Unmarshal(body, &data)
78-
data.Public = options.Public
79-
err = json.Unmarshal(body, &error_)
68+
var bucket Bucket
69+
_, err = c.Do(req, &bucket)
70+
if err != nil {
71+
return Bucket{}, err
72+
}
8073

81-
return data, error_
74+
return bucket, nil
8275
}
8376

84-
func (c *Client) UpdateBucket(id string, options BucketOptions) (MessageResponse, BucketResponseError) {
77+
// UpdateBucket creates a new Storage bucket
78+
// options.public The visibility of the bucket. Public buckets don't require an authorization token to download objects, but still require a valid token for all other operations. By default, buckets are private.
79+
// options.fileSizeLimit The maximum file size in bytes allowed in the bucket. By default, there is no limit.
80+
// options.allowedMimeTypes The list of allowed MIME types. By default, all MIME types are allowed.
81+
// return newly updated bucket id
82+
func (c *Client) UpdateBucket(id string, options BucketOptions) (MessageResponse, error) {
83+
bucketURL := c.clientTransport.baseUrl.String() + "/bucket/" + id
8584
bodyData := map[string]interface{}{
8685
"id": id,
8786
"name": id,
@@ -95,51 +94,45 @@ func (c *Client) UpdateBucket(id string, options BucketOptions) (MessageResponse
9594
if len(options.AllowedMimeTypes) > 0 {
9695
bodyData["allowed_mime_types"] = options.AllowedMimeTypes
9796
}
98-
jsonBody, _ := json.Marshal(bodyData)
99-
request, err := http.NewRequest(http.MethodPut, c.clientTransport.baseUrl.String()+"/bucket/"+id, bytes.NewBuffer(jsonBody))
100-
res, err := c.session.Do(request)
97+
req, err := c.NewRequest(http.MethodPut, bucketURL, &bodyData)
10198
if err != nil {
102-
panic(err)
99+
return MessageResponse{}, err
100+
}
101+
var message MessageResponse
102+
_, err = c.Do(req, &message)
103+
if err != nil {
104+
return MessageResponse{}, err
103105
}
104106

105-
body, err := io.ReadAll(res.Body)
106-
var data MessageResponse
107-
var error_ BucketResponseError
108-
err = json.Unmarshal(body, &data)
109-
err = json.Unmarshal(body, &error_)
110-
111-
return data, error_
107+
return message, nil
112108
}
113109

114-
func (c *Client) EmptyBucket(id string) (MessageResponse, BucketResponseError) {
110+
// EmptyBucket removes all objects inside a single bucket.
111+
func (c *Client) EmptyBucket(id string) (MessageResponse, error) {
112+
bucketURL := c.clientTransport.baseUrl.String() + "/bucket/" + id + "/empty"
115113
jsonBody, _ := json.Marshal(map[string]interface{}{})
116-
res, err := c.session.Post(c.clientTransport.baseUrl.String()+"/bucket/"+id+"/empty", "application/json", bytes.NewBuffer(jsonBody))
114+
req, err := c.NewRequest(http.MethodPost, bucketURL, &jsonBody)
117115
if err != nil {
118-
panic(err)
116+
return MessageResponse{}, err
119117
}
120118

121-
body, err := io.ReadAll(res.Body)
122-
var data MessageResponse
123-
var error_ BucketResponseError
124-
err = json.Unmarshal(body, &data)
125-
err = json.Unmarshal(body, &error_)
119+
var message MessageResponse
120+
_, err = c.Do(req, &message)
126121

127-
return data, error_
122+
return message, err
128123
}
129124

130-
func (c *Client) DeleteBucket(id string) (MessageResponse, BucketResponseError) {
125+
// DeleteBucket deletes an existing bucket. A bucket must be empty before it can be deleted.
126+
func (c *Client) DeleteBucket(id string) (MessageResponse, error) {
127+
bucketURL := c.clientTransport.baseUrl.String() + "/bucket/" + id
131128
jsonBody, _ := json.Marshal(map[string]interface{}{})
132-
request, err := http.NewRequest(http.MethodDelete, c.clientTransport.baseUrl.String()+"/bucket/"+id, bytes.NewBuffer(jsonBody))
133-
res, err := c.session.Do(request)
129+
req, err := c.NewRequest(http.MethodDelete, bucketURL, &jsonBody)
134130
if err != nil {
135-
panic(err)
131+
return MessageResponse{}, err
136132
}
137133

138-
body, err := io.ReadAll(res.Body)
139-
var data MessageResponse
140-
var error_ BucketResponseError
141-
err = json.Unmarshal(body, &data)
142-
err = json.Unmarshal(body, &error_)
134+
var message MessageResponse
135+
_, err = c.Do(req, &message)
143136

144-
return data, error_
137+
return message, err
145138
}

client.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package storage_go
22

33
import (
4+
"bytes"
5+
"encoding/json"
6+
"io"
47
"net/http"
58
"net/url"
69
)
@@ -59,3 +62,67 @@ func NewClient(rawUrl string, token string, headers map[string]string) *Client {
5962

6063
return &c
6164
}
65+
66+
// NewRequest will create new request with method, url and body
67+
// If body is not nil, it will be marshalled into json
68+
func (c *Client) NewRequest(method, url string, body ...interface{}) (*http.Request, error) {
69+
var buf io.ReadWriter
70+
if len(body) > 0 && body[0] != nil {
71+
buf = &bytes.Buffer{}
72+
enc := json.NewEncoder(buf)
73+
enc.SetEscapeHTML(false)
74+
err := enc.Encode(body[0])
75+
if err != nil {
76+
return nil, err
77+
}
78+
}
79+
req, err := http.NewRequest(method, url, buf)
80+
if err != nil {
81+
return nil, err
82+
}
83+
return req, nil
84+
}
85+
86+
// Do will send request using the c.sessionon which it is called
87+
// If response contains body, it will be unmarshalled into v
88+
// If response has err, it will be returned
89+
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
90+
resp, err := c.session.Do(req)
91+
if err != nil {
92+
return nil, err
93+
}
94+
95+
err = checkForError(resp)
96+
if err != nil {
97+
return resp, err
98+
}
99+
100+
if resp.Body != nil && v != nil {
101+
defer resp.Body.Close()
102+
body, err := io.ReadAll(resp.Body)
103+
if err != nil {
104+
return resp, err
105+
}
106+
err = json.Unmarshal(body, &v)
107+
if err != nil {
108+
return resp, err
109+
}
110+
}
111+
112+
return resp, nil
113+
}
114+
115+
func checkForError(resp *http.Response) error {
116+
if c := resp.StatusCode; 200 <= c && c < 400 {
117+
return nil
118+
}
119+
120+
errorResponse := &StorageError{}
121+
122+
data, err := io.ReadAll(resp.Body)
123+
if err == nil && data != nil {
124+
_ = json.Unmarshal(data, errorResponse)
125+
}
126+
127+
return errorResponse
128+
}

error.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package storage_go
2+
3+
type StorageError struct {
4+
Status int `json:"status"`
5+
Message string `json:"message"`
6+
}
7+
8+
func (e *StorageError) Error() string {
9+
return e.Message
10+
}
11+
12+
func NewStorageError(err error, statusCode int) StorageError {
13+
return StorageError{
14+
Status: statusCode,
15+
Message: err.Error(),
16+
}
17+
}

0 commit comments

Comments
 (0)