169 lines
2.6 KiB
Go
169 lines
2.6 KiB
Go
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
|
|
}
|
|
|