package api import "encoding/json" import "net/http" import "net/url" import "errors" import "bytes" import "fmt" import "io" type RequestOptions struct { Method string Body interface{} Headers map[string]string } func (client *Client) doRawRequest( u *url.URL, params RequestOptions, result interface{}, ) error { var ( err error ) client.requestsMade++ reqBody := new(bytes.Buffer) if params.Body != nil { encoder := json.NewEncoder(reqBody) err := encoder.Encode(params.Body) if err != nil { return err } } request, err := http.NewRequest( params.Method, u.String(), reqBody, ) if err != nil { return err } if params.Headers != nil { for k, v := range params.Headers { request.Header.Set(k, v) } } res, err := http.DefaultClient.Do(request) if client.Debug { client.Printf( "Request: %+v\n\nAmo response: %+v\n\n", request, res, ) } if res == nil { if err != nil { return NewRequestError(err) } return NewRequestError(ErrUnreachable) } if err != nil { return NewRequestError(fmt.Errorf( "%w: %d %s %s", err, res.StatusCode, params.Method, u, )) } defer res.Body.Close() if res.StatusCode == 204 { return NewRequestError(ErrNoContent) } if res.StatusCode >= 400 { var specErr error if res.StatusCode == 401 { specErr = ErrNoAuth } resErrInfo, _ := io.ReadAll(res.Body) return NewRequestError(fmt.Errorf( "%w: %s %s %q %d", specErr, params.Method, u, string(resErrInfo), res.StatusCode, )) } if result != nil { decoder := json.NewDecoder(res.Body) err = decoder.Decode(result) if err != nil { return err } } return nil } func (client *Client) doRequest( u string, params RequestOptions, result any, ) error { var ( err error parsedURL *url.URL ) if client.waitInQueue() { defer client.finishRequest() } parsedURL, err = url.Parse(u) if err != nil { return err } reqURL := client.BaseURL.ResolveReference(parsedURL) err = client.doRawRequest( reqURL, params, result, ) if errors.Is(err, ErrNoAuth) && client.options.RefreshToken != "" { _, err = client.RefreshToken() if err != nil { return nil } return client.doRawRequest( reqURL, params, result, ) } else if err != nil { return err } return nil } func makeHeaders( token string, ) map[string]string { headers := map[string]string{ "Accept": DefaultAccept, "Cache-Control": DefaultCacheControl, "Content-Type": DefaultContentType, } if len(token) > 0 { headers["Authorization"] = fmt.Sprintf("Bearer %s", token) } return headers }