diff --git a/addon/adapter.go b/addon/adapter.go index f9ffab673..6f5d8f147 100644 --- a/addon/adapter.go +++ b/addon/adapter.go @@ -9,6 +9,7 @@ import ( logapi "github.com/go-logr/logr" "github.com/jortel/go-utils/logr" + "github.com/konveyor/tackle2-hub/api" "github.com/konveyor/tackle2-hub/binding" "github.com/konveyor/tackle2-hub/settings" "github.com/konveyor/tackle2-hub/task" @@ -131,7 +132,7 @@ func (h *Adapter) Run(addon func() error) { // newAdapter builds a new Addon Adapter object. func newAdapter() (adapter *Adapter) { richClient := binding.New(Settings.Addon.Hub.URL) - richClient.Client.SetToken(Settings.Addon.Hub.Token) + richClient.Client.SetToken(api.Login{Token: Settings.Addon.Hub.Token}) adapter = &Adapter{ client: richClient.Client, Task: Task{ diff --git a/binding/client.go b/binding/client.go index 4a502aea1..83ec15b73 100644 --- a/binding/client.go +++ b/binding/client.go @@ -69,7 +69,7 @@ func (s Path) Inject(p Params) (out string) { } // NewClient Constructs a new client -func NewClient(url, token string) (client *Client) { +func NewClient(url string, token api.Login) (client *Client) { client = &Client{ baseURL: url, token: token, @@ -83,7 +83,7 @@ type Client struct { // baseURL for the nub. baseURL string // addon API token - token string + token api.Login // transport transport http.RoundTripper // Retry limit. @@ -93,7 +93,7 @@ type Client struct { } // SetToken sets hub token on client -func (r *Client) SetToken(token string) { +func (r *Client) SetToken(token api.Login) { r.token = token } @@ -636,7 +636,7 @@ func (r *Client) send(rb func() (*http.Request, error)) (response *http.Response if err != nil { return } - request.Header.Set(api.Authorization, r.token) + request.Header.Set(api.Authorization, r.token.Token) client := http.Client{Transport: r.transport} response, err = client.Do(request) if err != nil { @@ -662,6 +662,17 @@ func (r *Client) send(rb func() (*http.Request, error)) (response *http.Response response.StatusCode, request.Method, request.URL.Path)) + if response.StatusCode == http.StatusUnauthorized { + refreshed, nErr := r.refreshToken(request) + if nErr != nil { + r.Error = liberr.Wrap(nErr) + err = r.Error + return + } + if refreshed { + continue + } + } break } } @@ -765,3 +776,22 @@ func (f *Field) disposition() (d string) { d = fmt.Sprintf(`form-data; name="%s"; filename="%s"`, f.Name, pathlib.Base(f.Path)) return } + +// refreshToken refreshes the token. +func (r *Client) refreshToken(request *http.Request) (refreshed bool, err error) { + if r.token.Token == "" || + strings.HasSuffix(request.URL.Path, api.AuthRefreshRoot) { + return + } + login := &api.Login{Refresh: r.token.Refresh} + err = r.Post(api.AuthRefreshRoot, login) + if err == nil { + r.token.Token = login.Token + refreshed = true + return + } + if errors.Is(err, &RestError{}) { + err = nil + } + return +} diff --git a/binding/richclient.go b/binding/richclient.go index 6bfc03854..118a55d6b 100644 --- a/binding/richclient.go +++ b/binding/richclient.go @@ -53,7 +53,7 @@ type RichClient struct { func New(baseUrl string) (r *RichClient) { // // Build REST client. - client := NewClient(baseUrl, "") + client := NewClient(baseUrl, api.Login{}) // // Build RichClient. @@ -142,6 +142,6 @@ func (r *RichClient) Login(user, password string) (err error) { if err != nil { return } - r.Client.SetToken(login.Token) + r.Client.SetToken(login) return } diff --git a/test/api/client/client.go b/test/api/client/client.go index e450720bc..6129af88c 100644 --- a/test/api/client/client.go +++ b/test/api/client/client.go @@ -28,7 +28,7 @@ func PrepareRichClient() (richClient *binding.RichClient) { } // Disable HTTP requests retry for network-related errors to fail quickly. - richClient.Client.Retry = 0 + richClient.Client.Retry = 1 return }