Merge pull request #77 from apourchet/apourchet/fix-race-sendwithauth

Locking SendWithAuth to fix race condition
This commit is contained in:
Alex Pliutau 2019-03-01 10:49:21 +01:00 committed by GitHub
commit 114f3ab4be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 10 additions and 0 deletions

View File

@ -125,10 +125,15 @@ func (c *Client) Send(req *http.Request, v interface{}) error {
// making the main request // making the main request
// client.Token will be updated when changed // client.Token will be updated when changed
func (c *Client) SendWithAuth(req *http.Request, v interface{}) error { func (c *Client) SendWithAuth(req *http.Request, v interface{}) error {
c.Lock()
// Note: Here we do not want to `defer c.Unlock()` because we need `c.Send(...)`
// to happen outside of the locked section.
if c.Token != nil { if c.Token != nil {
if !c.tokenExpiresAt.IsZero() && c.tokenExpiresAt.Sub(time.Now()) < RequestNewTokenBeforeExpiresIn { if !c.tokenExpiresAt.IsZero() && c.tokenExpiresAt.Sub(time.Now()) < RequestNewTokenBeforeExpiresIn {
// c.Token will be updated in GetAccessToken call // c.Token will be updated in GetAccessToken call
if _, err := c.GetAccessToken(); err != nil { if _, err := c.GetAccessToken(); err != nil {
c.Unlock()
return err return err
} }
} }
@ -136,6 +141,9 @@ func (c *Client) SendWithAuth(req *http.Request, v interface{}) error {
req.Header.Set("Authorization", "Bearer "+c.Token.Token) req.Header.Set("Authorization", "Bearer "+c.Token.Token)
} }
// Unlock the client mutex before sending the request, this allows multiple requests
// to be in progress at the same time.
c.Unlock()
return c.Send(req, v) return c.Send(req, v)
} }

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"sync"
"time" "time"
) )
@ -168,6 +169,7 @@ type (
// Client represents a Paypal REST API Client // Client represents a Paypal REST API Client
Client struct { Client struct {
sync.Mutex
Client *http.Client Client *http.Client
ClientID string ClientID string
Secret string Secret string