github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/pkg/manager/client.go (about) 1 // Package manager is used for interacting with the cloudery. 2 package manager 3 4 import ( 5 "bytes" 6 "context" 7 "encoding/json" 8 "errors" 9 "io" 10 "net/http" 11 "time" 12 13 "github.com/labstack/echo/v4" 14 "golang.org/x/oauth2" 15 ) 16 17 // tokenSource implements the oauth2.TokenSource interface 18 type tokenSource struct { 19 token string 20 } 21 22 func (t *tokenSource) Token() (*oauth2.Token, error) { 23 token := &oauth2.Token{ 24 AccessToken: t.token, 25 } 26 return token, nil 27 } 28 29 // APIClient is an http client that can be used to query the API of the 30 // manager. 31 type APIClient struct { 32 baseURL string 33 client *http.Client 34 } 35 36 // NewAPIClient builds a new client for the manager API 37 func NewAPIClient(baseURL, token string) *APIClient { 38 tokenSource := &tokenSource{token: token} 39 client := oauth2.NewClient(context.Background(), tokenSource) 40 client.Timeout = 15 * time.Second 41 return &APIClient{ 42 baseURL: baseURL, 43 client: client, 44 } 45 } 46 47 // Do makes a request to the manager API 48 func (c *APIClient) Do(method, url string, body io.Reader) (*http.Response, error) { 49 req, err := http.NewRequest(method, c.baseURL+url, body) 50 if err != nil { 51 return nil, err 52 } 53 if body != nil { 54 req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) 55 } 56 return c.client.Do(req) 57 } 58 59 // Get makes a GET request to the manager API 60 func (c *APIClient) Get(url string) (map[string]interface{}, error) { 61 res, err := c.Do(http.MethodGet, url, nil) 62 if err != nil { 63 return nil, err 64 } 65 defer res.Body.Close() 66 if res.StatusCode >= 400 { 67 return nil, errors.New(res.Status) 68 } 69 var data map[string]interface{} 70 if err := json.NewDecoder(res.Body).Decode(&data); err != nil { 71 return nil, err 72 } 73 return data, nil 74 } 75 76 // Post makes a POST request to the manager API 77 func (c *APIClient) Post(url string, body io.Reader) error { 78 res, err := c.Do(http.MethodPost, url, body) 79 if err != nil { 80 return err 81 } 82 if err := res.Body.Close(); err != nil { 83 return err 84 } 85 if res.StatusCode >= 400 { 86 return errors.New(res.Status) 87 } 88 return nil 89 } 90 91 // Put makes a PUT request to the manager API 92 func (c *APIClient) Put(url string, params map[string]interface{}) error { 93 body, err := json.Marshal(params) 94 if err != nil { 95 return err 96 } 97 reader := bytes.NewReader(body) 98 res, err := c.Do(http.MethodPut, url, reader) 99 if err != nil { 100 return err 101 } 102 if err := res.Body.Close(); err != nil { 103 return err 104 } 105 if res.StatusCode >= 400 { 106 return errors.New(res.Status) 107 } 108 return nil 109 } 110 111 // Delete makes a DELETE request to the manager API 112 func (c *APIClient) Delete(url string) error { 113 res, err := c.Do(http.MethodDelete, url, nil) 114 if err != nil { 115 return err 116 } 117 if err := res.Body.Close(); err != nil { 118 return err 119 } 120 if res.StatusCode >= 400 { 121 return errors.New(res.Status) 122 } 123 return nil 124 }