fix: better errors.
This commit is contained in:
parent
ebd4866455
commit
28f6a7e2ec
3 changed files with 63 additions and 43 deletions
|
@ -2,6 +2,8 @@ package amo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
"errors"
|
||||||
"vultras.su/core/amo/api"
|
"vultras.su/core/amo/api"
|
||||||
"vultras.su/core/amo/companies"
|
"vultras.su/core/amo/companies"
|
||||||
"vultras.su/core/amo/contacts"
|
"vultras.su/core/amo/contacts"
|
||||||
|
@ -92,7 +94,8 @@ func (client *Client) GetEvents(req events.EventsRequest) ([]events.Event, error
|
||||||
resp := events.EventsResponse{}
|
resp := events.EventsResponse{}
|
||||||
err := client.Api.Get(res, &resp, abs)
|
err := client.Api.Get(res, &resp, abs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == api.NoContentErr {
|
// Return empty if no content avialable.
|
||||||
|
if errors.Is(err, api.NoContentErr) {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -101,6 +104,7 @@ func (client *Client) GetEvents(req events.EventsRequest) ([]events.Event, error
|
||||||
if resp.Links.Next.Href == "" {
|
if resp.Links.Next.Href == "" {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
time.Sleep(time.Millisecond*300)
|
||||||
abs = true
|
abs = true
|
||||||
res = resp.Links.Next.Href
|
res = resp.Links.Next.Href
|
||||||
}
|
}
|
||||||
|
|
87
api/api.go
87
api/api.go
|
@ -1,16 +1,17 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"errors"
|
||||||
|
"bytes"
|
||||||
|
"time"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -35,10 +36,11 @@ type ClientOptions struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
*log.Logger
|
||||||
options *ClientOptions
|
options *ClientOptions
|
||||||
BaseUrl *url.URL
|
BaseUrl *url.URL
|
||||||
secretStoreFilePath string
|
secretStoreFilePath string
|
||||||
Debug bool `json`
|
Debug bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type requestOptions struct {
|
type requestOptions struct {
|
||||||
|
@ -60,42 +62,43 @@ type TokenPair struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewApi(secretPath string) (*Client, error) {
|
func NewApi(secretPath string) (*Client, error) {
|
||||||
ret := &Client{
|
client := &Client{
|
||||||
|
Logger: log.New(os.Stdout, "AmoCRM client: ", log.Ldate | log.Ltime),
|
||||||
secretStoreFilePath: secretPath,
|
secretStoreFilePath: secretPath,
|
||||||
}
|
}
|
||||||
options, err := ret.readSecret()
|
options, err := client.readSecret()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, NewApiError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if client.Debug {
|
||||||
|
client.Printf("ClientOptions: %v\n", options)
|
||||||
}
|
}
|
||||||
fmt.Println("opts:", options)
|
|
||||||
|
|
||||||
if options.Url == "" || options.RedirectUrl == "" {
|
if options.Url == "" || options.RedirectUrl == "" {
|
||||||
return nil, errors.New("AmoCrm: Invalid options: Url")
|
return nil, NewApiError(InvalidUrlOptionsErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
resolvedUrl, err := url.Parse(options.Url)
|
resolvedUrl, err := url.Parse(options.Url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, NewApiError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.BaseUrl = resolvedUrl
|
client.BaseUrl = resolvedUrl
|
||||||
|
client.options = options
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ret.options = options
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
//pair *TokenPair
|
//pair *TokenPair
|
||||||
exchangeErr error
|
exchangeErr error
|
||||||
exchanged bool
|
exchanged bool
|
||||||
)
|
)
|
||||||
if ret.options.AccessToken == "" && ret.options.RefreshToken == "" {
|
if client.options.AccessToken == "" && client.options.RefreshToken == "" {
|
||||||
if ret.options.ClientSecret == "" ||
|
if client.options.ClientSecret == "" ||
|
||||||
ret.options.ClientId == "" ||
|
client.options.ClientId == "" ||
|
||||||
ret.options.AuthCode == "" {
|
client.options.AuthCode == "" {
|
||||||
return nil, errors.New("AmoCrm: invalid options: ExchangeAuth")
|
return nil, NewApiError(InvalidExchangeAuthOptionsErr)
|
||||||
}
|
}
|
||||||
_, exchangeErr = ret.ExchangeAuth()
|
_, exchangeErr = client.ExchangeAuth()
|
||||||
exchanged = true
|
exchanged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,16 +106,13 @@ func NewApi(secretPath string) (*Client, error) {
|
||||||
// Refreshing token before the work.
|
// Refreshing token before the work.
|
||||||
// Should think of how often should refresh
|
// Should think of how often should refresh
|
||||||
// the token. (see the ExpiresIn)
|
// the token. (see the ExpiresIn)
|
||||||
_, err = ret.RefreshToken()
|
_, err = client.RefreshToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, NewApiError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Client{
|
return client, nil
|
||||||
options: options,
|
|
||||||
BaseUrl: resolvedUrl,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *Client) readSecret() (*ClientOptions, error) {
|
func (api *Client) readSecret() (*ClientOptions, error) {
|
||||||
|
@ -190,37 +190,40 @@ func (api *Client) rdoRequest(resourceUrl string, requestParams requestOptions,
|
||||||
|
|
||||||
response, err := http.DefaultClient.Do(request)
|
response, err := http.DefaultClient.Do(request)
|
||||||
if api.Debug {
|
if api.Debug {
|
||||||
fmt.Printf("\nAmo request: %+v\nAmo repsonse: %+v\n", request, response)
|
api.Printf("Request: %+v\n\nAmo response: %+v\n\n", request, response)
|
||||||
}
|
}
|
||||||
if response == nil {
|
if response == nil {
|
||||||
return NoInternetErr
|
return RequestError(NoInternetErr)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New(fmt.Sprintf(
|
return RequestError(fmt.Errorf(
|
||||||
"Request error: %s %d %s %s",
|
"%w: %d %s %s",
|
||||||
err.Error(),
|
err,
|
||||||
response.StatusCode,
|
response.StatusCode,
|
||||||
requestParams.HttpMethod,
|
requestParams.HttpMethod,
|
||||||
resourceUrl,
|
resourceUrl,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
|
|
||||||
if response.StatusCode == 204 {
|
if response.StatusCode == 204 {
|
||||||
return NoContentErr
|
return RequestError(NoContentErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if response.StatusCode >= 400 {
|
if response.StatusCode >= 400 {
|
||||||
|
var specErr error
|
||||||
if response.StatusCode == 401 {
|
if response.StatusCode == 401 {
|
||||||
return NoAuthErr
|
specErr = NoAuthErr
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyBytes, _ := ioutil.ReadAll(response.Body)
|
responseErrorInfo, _ := ioutil.ReadAll(response.Body)
|
||||||
return errors.New(fmt.Sprintf(
|
return RequestError(fmt.Errorf(
|
||||||
"%s %d %s %s",
|
"%w: %s %s %q %d",
|
||||||
string(bodyBytes),
|
specErr,
|
||||||
response.StatusCode,
|
|
||||||
requestParams.HttpMethod,
|
requestParams.HttpMethod,
|
||||||
resourceUrl,
|
resourceUrl,
|
||||||
|
string(responseErrorInfo),
|
||||||
|
response.StatusCode,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +242,7 @@ func (api *Client) doRequest(
|
||||||
) error {
|
) error {
|
||||||
var err error
|
var err error
|
||||||
err = api.rdoRequest(resourceUrl, requestParams, result)
|
err = api.rdoRequest(resourceUrl, requestParams, result)
|
||||||
if err == NoAuthErr && api.options.RefreshToken != "" {
|
if errors.Is(err, NoAuthErr) && api.options.RefreshToken != "" {
|
||||||
_, err = api.RefreshToken()
|
_, err = api.RefreshToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -2,10 +2,23 @@ package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
NoContentErr = errors.New("no content")
|
NoContentErr = errors.New("no content")
|
||||||
NoAuthErr = errors.New("not authorized")
|
NoAuthErr = errors.New("not authorized")
|
||||||
NoInternetErr = errors.New("no Internet provided")
|
NoInternetErr = errors.New("no Internet provided")
|
||||||
|
InvalidUrlOptionsErr = errors.New("invalid URL options")
|
||||||
|
InvalidExchangeAuthOptionsErr = errors.New("invalid ExchangeAuth options")
|
||||||
|
UrlParsingErr = errors.New("URL parsing")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func NewApiError(err error) error {
|
||||||
|
return fmt.Errorf("NewApi: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RequestError(err error) error {
|
||||||
|
return fmt.Errorf("RequestError: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue