From 28e740b35b469fda465f7bd30821bc3aad8d5e41 Mon Sep 17 00:00:00 2001 From: Shahrad Elahi Date: Tue, 23 Dec 2025 04:15:34 +0000 Subject: [PATCH] refactor(api): unify API request handling --- cloudflare/api.go | 369 ++++++---------------------------------------- 1 file changed, 46 insertions(+), 323 deletions(-) diff --git a/cloudflare/api.go b/cloudflare/api.go index 52136e9..b4ccde6 100644 --- a/cloudflare/api.go +++ b/cloudflare/api.go @@ -45,84 +45,55 @@ func NewWarpAPI() *WarpAPI { } } -func (w *WarpAPI) GetAccount(authToken, deviceID string) (model.IdentityAccount, error) { - reqUrl := fmt.Sprintf("%s/reg/%s/account", apiBase, deviceID) - method := "GET" +func (w *WarpAPI) request(method, url, authToken string, body interface{}, out interface{}) error { + var bodyReader io.Reader + if body != nil { + jsonBody, err := json.Marshal(body) + if err != nil { + return err + } + bodyReader = bytes.NewBuffer(jsonBody) + } - req, err := http.NewRequest(method, reqUrl, nil) + req, err := http.NewRequest(method, url, bodyReader) if err != nil { - return model.IdentityAccount{}, err + return err } - // Set headers for k, v := range defaultHeaders() { req.Header.Set(k, v) } - req.Header.Set("Authorization", "Bearer "+authToken) + if authToken != "" { + req.Header.Set("Authorization", "Bearer "+authToken) + } - // Create HTTP client and execute request resp, err := w.client.Do(req) if err != nil { - return model.IdentityAccount{}, err + return err } defer resp.Body.Close() if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return model.IdentityAccount{}, fmt.Errorf("API request failed with status: %s", resp.Status) + return fmt.Errorf("API request failed with status: %s", resp.Status) } - // convert response to byte array - responseData, err := io.ReadAll(resp.Body) - if err != nil { - return model.IdentityAccount{}, err + if out != nil { + return json.NewDecoder(resp.Body).Decode(out) } - var rspData = model.IdentityAccount{} - if err := json.Unmarshal(responseData, &rspData); err != nil { - return model.IdentityAccount{}, err - } + return nil +} - return rspData, nil +func (w *WarpAPI) GetAccount(authToken, deviceID string) (model.IdentityAccount, error) { + var rspData model.IdentityAccount + err := w.request("GET", fmt.Sprintf("%s/reg/%s/account", apiBase, deviceID), authToken, nil, &rspData) + return rspData, err } func (w *WarpAPI) GetBoundDevices(authToken, deviceID string) ([]model.IdentityDevice, error) { - reqUrl := fmt.Sprintf("%s/reg/%s/account/devices", apiBase, deviceID) - method := "GET" - - req, err := http.NewRequest(method, reqUrl, nil) - if err != nil { - return nil, err - } - - // Set headers - for k, v := range defaultHeaders() { - req.Header.Set(k, v) - } - req.Header.Set("Authorization", "Bearer "+authToken) - - // Create HTTP client and execute request - resp, err := w.client.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return nil, fmt.Errorf("API request failed with status: %s", resp.Status) - } - - // convert response to byte array - responseData, err := io.ReadAll(resp.Body) - if err != nil { - return nil, err - } - - var rspData = []model.IdentityDevice{} - if err := json.Unmarshal(responseData, &rspData); err != nil { - return nil, err - } - - return rspData, nil + var rspData []model.IdentityDevice + err := w.request("GET", fmt.Sprintf("%s/reg/%s/account/devices", apiBase, deviceID), authToken, nil, &rspData) + return rspData, err } func (w *WarpAPI) GetSourceBoundDevice(authToken, deviceID string) (*model.IdentityDevice, error) { @@ -141,49 +112,12 @@ func (w *WarpAPI) GetSourceBoundDevice(authToken, deviceID string) (*model.Ident } func (w *WarpAPI) GetSourceDevice(authToken, deviceID string) (model.Identity, error) { - reqUrl := fmt.Sprintf("%s/reg/%s", apiBase, deviceID) - method := "GET" - - req, err := http.NewRequest(method, reqUrl, nil) - if err != nil { - return model.Identity{}, err - } - - // Set headers - for k, v := range defaultHeaders() { - req.Header.Set(k, v) - } - req.Header.Set("Authorization", "Bearer "+authToken) - - // Create HTTP client and execute request - resp, err := w.client.Do(req) - if err != nil { - return model.Identity{}, err - } - defer resp.Body.Close() - - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return model.Identity{}, fmt.Errorf("API request failed with status: %s", resp.Status) - } - - // convert response to byte array - responseData, err := io.ReadAll(resp.Body) - if err != nil { - return model.Identity{}, err - } - - var rspData = model.Identity{} - if err := json.Unmarshal(responseData, &rspData); err != nil { - return model.Identity{}, err - } - - return rspData, nil + var rspData model.Identity + err := w.request("GET", fmt.Sprintf("%s/reg/%s", apiBase, deviceID), authToken, nil, &rspData) + return rspData, err } func (w *WarpAPI) Register(publicKey string) (model.Identity, error) { - reqUrl := fmt.Sprintf("%s/reg", apiBase) - method := "POST" - data := map[string]interface{}{ "install_id": "", "fcm_token": "", @@ -195,251 +129,40 @@ func (w *WarpAPI) Register(publicKey string) (model.Identity, error) { "warp_enabled": true, } - jsonBody, err := json.Marshal(data) - if err != nil { - return model.Identity{}, err - } - - req, err := http.NewRequest(method, reqUrl, bytes.NewBuffer(jsonBody)) - if err != nil { - return model.Identity{}, err - } - - // Set headers - for k, v := range defaultHeaders() { - req.Header.Set(k, v) - } - - // Create HTTP client and execute request - resp, err := w.client.Do(req) - if err != nil { - return model.Identity{}, err - } - defer resp.Body.Close() - - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return model.Identity{}, fmt.Errorf("API request failed with status: %s", resp.Status) - } - - // convert response to byte array - responseData, err := io.ReadAll(resp.Body) - if err != nil { - return model.Identity{}, err - } - - var rspData = model.Identity{} - if err := json.Unmarshal(responseData, &rspData); err != nil { - return model.Identity{}, err - } - - return rspData, nil + var rspData model.Identity + err := w.request("POST", fmt.Sprintf("%s/reg", apiBase), "", data, &rspData) + return rspData, err } func (w *WarpAPI) ResetAccountLicense(authToken, deviceID string) (model.License, error) { - reqUrl := fmt.Sprintf("%s/reg/%s/account/license", apiBase, deviceID) - method := "POST" - - req, err := http.NewRequest(method, reqUrl, nil) - if err != nil { - return model.License{}, err - } - - // Set headers - for k, v := range defaultHeaders() { - req.Header.Set(k, v) - } - req.Header.Set("Authorization", "Bearer "+authToken) - - // Create HTTP client and execute request - resp, err := w.client.Do(req) - if err != nil { - return model.License{}, err - } - defer resp.Body.Close() - - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return model.License{}, fmt.Errorf("API request failed with response: %s", resp.Status) - } - - // convert response to byte array - responseData, err := io.ReadAll(resp.Body) - if err != nil { - return model.License{}, err - } - - var rspData = model.License{} - if err := json.Unmarshal(responseData, &rspData); err != nil { - return model.License{}, err - } - - return rspData, nil + var rspData model.License + err := w.request("POST", fmt.Sprintf("%s/reg/%s/account/license", apiBase, deviceID), authToken, nil, &rspData) + return rspData, err } func (w *WarpAPI) UpdateAccount(authToken, deviceID, license string) (model.IdentityAccount, error) { - reqUrl := fmt.Sprintf("%s/reg/%s/account", apiBase, deviceID) - method := "PUT" - - jsonBody, err := json.Marshal(map[string]interface{}{"license": license}) - if err != nil { - return model.IdentityAccount{}, err - } - - req, err := http.NewRequest(method, reqUrl, bytes.NewBuffer(jsonBody)) - if err != nil { - return model.IdentityAccount{}, err - } - - // Set headers - for k, v := range defaultHeaders() { - req.Header.Set(k, v) - } - req.Header.Set("Authorization", "Bearer "+authToken) - - // Create HTTP client and execute request - resp, err := w.client.Do(req) - if err != nil { - return model.IdentityAccount{}, err - } - defer resp.Body.Close() - - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return model.IdentityAccount{}, fmt.Errorf("API request failed with status: %s", resp.Status) - } - - // convert response to byte array - responseData, err := io.ReadAll(resp.Body) - if err != nil { - return model.IdentityAccount{}, err - } - - var rspData = model.IdentityAccount{} - if err := json.Unmarshal(responseData, &rspData); err != nil { - return model.IdentityAccount{}, err - } - - return rspData, nil + var rspData model.IdentityAccount + err := w.request("PUT", fmt.Sprintf("%s/reg/%s/account", apiBase, deviceID), authToken, map[string]interface{}{"license": license}, &rspData) + return rspData, err } func (w *WarpAPI) UpdateBoundDevice(authToken, deviceID, otherDeviceID, name string, active bool) (model.IdentityDevice, error) { - reqUrl := fmt.Sprintf("%s/reg/%s/account/devices/%s", apiBase, deviceID, otherDeviceID) - method := "PATCH" - data := map[string]interface{}{ "active": active, "name": name, } - jsonBody, err := json.Marshal(data) - if err != nil { - return model.IdentityDevice{}, err - } - - req, err := http.NewRequest(method, reqUrl, bytes.NewBuffer(jsonBody)) - if err != nil { - return model.IdentityDevice{}, err - } - - // Set headers - for k, v := range defaultHeaders() { - req.Header.Set(k, v) - } - req.Header.Set("Authorization", "Bearer "+authToken) - - // Create HTTP client and execute request - resp, err := w.client.Do(req) - if err != nil { - return model.IdentityDevice{}, err - } - defer resp.Body.Close() - - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return model.IdentityDevice{}, fmt.Errorf("API request failed with status: %s", resp.Status) - } - - // convert response to byte array - responseData, err := io.ReadAll(resp.Body) - if err != nil { - return model.IdentityDevice{}, err - } - - var rspData = model.IdentityDevice{} - if err := json.Unmarshal(responseData, &rspData); err != nil { - return model.IdentityDevice{}, err - } - - return rspData, nil + var rspData model.IdentityDevice + err := w.request("PATCH", fmt.Sprintf("%s/reg/%s/account/devices/%s", apiBase, deviceID, otherDeviceID), authToken, data, &rspData) + return rspData, err } func (w *WarpAPI) UpdateSourceDevice(authToken, deviceID string, data map[string]interface{}) (model.Identity, error) { - reqUrl := fmt.Sprintf("%s/reg/%s", apiBase, deviceID) - method := "PATCH" - - jsonBody, err := json.Marshal(data) - if err != nil { - return model.Identity{}, err - } - - req, err := http.NewRequest(method, reqUrl, bytes.NewBuffer(jsonBody)) - if err != nil { - return model.Identity{}, err - } - - // Set headers - for k, v := range defaultHeaders() { - req.Header.Set(k, v) - } - req.Header.Set("Authorization", "Bearer "+authToken) - - // Create HTTP client and execute request - resp, err := w.client.Do(req) - if err != nil { - return model.Identity{}, err - } - defer resp.Body.Close() - - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return model.Identity{}, fmt.Errorf("API request failed with status: %s", resp.Status) - } - - // convert response to byte array - responseData, err := io.ReadAll(resp.Body) - if err != nil { - return model.Identity{}, err - } - - var rspData = model.Identity{} - if err := json.Unmarshal(responseData, &rspData); err != nil { - return model.Identity{}, err - } - - return rspData, nil + var rspData model.Identity + err := w.request("PATCH", fmt.Sprintf("%s/reg/%s", apiBase, deviceID), authToken, data, &rspData) + return rspData, err } func (w *WarpAPI) DeleteDevice(authToken, deviceID string) error { - reqUrl := fmt.Sprintf("%s/reg/%s", apiBase, deviceID) - method := "DELETE" - - req, err := http.NewRequest(method, reqUrl, nil) - if err != nil { - return err - } - - // Set headers - for k, v := range defaultHeaders() { - req.Header.Set(k, v) - } - req.Header.Set("Authorization", "Bearer "+authToken) - - // Create HTTP client and execute request - resp, err := w.client.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return fmt.Errorf("API request failed with status: %s", resp.Status) - } - - return nil + return w.request("DELETE", fmt.Sprintf("%s/reg/%s", apiBase, deviceID), authToken, nil, nil) }