From 58513eb0ea718859ce54c5af6c35ad6d2ce2a19c Mon Sep 17 00:00:00 2001 From: Burcu Dogan Date: Mon, 26 May 2014 14:45:41 +0200 Subject: [PATCH] Provide a transport constructor for transporters with a cache. --- cache.go | 47 ++++++++++++++++++++--------------------------- cache_test.go | 21 ++++++++++----------- oauth2.go | 9 +++++++++ transport.go | 7 ------- 4 files changed, 39 insertions(+), 45 deletions(-) diff --git a/cache.go b/cache.go index b599d37..16653e2 100644 --- a/cache.go +++ b/cache.go @@ -12,46 +12,39 @@ import ( // Cache represents a token cacher. type Cache interface { - // Token returns the initial token retrieved from the cache, - // if there is no existing token nil value is returned. - Token() (token *Token) + // Reads a cached token. + // It may return a nil value if no token is cached. + Read() (token *Token, err error) // Write writes a token to the specified file. Write(token *Token) } // NewFileCache creates a new file cache. -func NewFileCache(filename string) (cache *FileCache, err error) { - data, err := ioutil.ReadFile(filename) - if os.IsNotExist(err) { - // no token has cached before, skip reading - return &FileCache{filename: filename}, nil - } - if err != nil { - return - } - var token Token - if err = json.Unmarshal(data, &token); err != nil { - return - } - cache = &FileCache{filename: filename, initialToken: &token} - return +func NewFileCache(filename string) (cache *FileCache) { + return &FileCache{filename: filename} } // FileCache represents a file based token cacher. type FileCache struct { - // Handler to be invoked if an error occurs - // during read or write operations. + // Handler to be invoked if an error occurs during writing. ErrorHandler func(error) - initialToken *Token - filename string + filename string } -// Token returns the initial token read from the cache. It should be used to -// warm the authorization mechanism, token refreshes and later writes don't -// change the returned value. If no token is cached before, returns nil. -func (f *FileCache) Token() (token *Token) { - return f.initialToken +func (f *FileCache) Read() (token *Token, err error) { + data, err := ioutil.ReadFile(f.filename) + if os.IsNotExist(err) { + // no token has cached before, skip reading + return nil, nil + } + if err != nil { + return + } + if err = json.Unmarshal(data, &token); err != nil { + return + } + return } // Write writes a token to the specified file. diff --git a/cache_test.go b/cache_test.go index 2fd5efe..a024811 100644 --- a/cache_test.go +++ b/cache_test.go @@ -12,13 +12,14 @@ import ( var tokenBody = `{"access_token":"abc123","token_type":"Bearer","refresh_token":"def789","expiry":"0001-01-01T00:00:00Z"}` -func TestNewFileCacheNotExist(t *testing.T) { - cache, err := NewFileCache("/path/that/doesnt/exist") +func TestFileCacheReadNotExist(t *testing.T) { + cache := NewFileCache("/path/that/doesnt/exist") + token, err := cache.Read() if err != nil { t.Fatalf("NewFileCache shouldn't return an error for if cache file doesn't exist, but returned %v", err) } - if cache == nil { - t.Fatalf("A file cache should be inited with a non existing cache file") + if token != nil { + t.Fatalf("Token should be nil, but found %v", token) } } @@ -32,11 +33,12 @@ func TestNewFileCache(t *testing.T) { t.Fatal(err) } - cache, err := NewFileCache(f.Name()) + cache := NewFileCache(f.Name()) + token, err := cache.Read() if err != nil { - t.Fatalf("Cache should have read the file cache at %v, but recieved %v", f.Name(), err) + t.Fatal(err) } - token := cache.Token() + if token.AccessToken != "abc123" { t.Fatalf("Cached access token is %v, expected to be abc123", token.AccessToken) } @@ -51,15 +53,12 @@ func TestFileCacheWrite(t *testing.T) { t.Fatal(err) } - cache, err := NewFileCache(path.Join(dirName, "cache-file")) + cache := NewFileCache(path.Join(dirName, "cache-file")) cache.ErrorHandler = func(err error) { if err != nil { t.Fatalf("Cache write should have been succeeded succesfully, recieved %v", err) } } - if err != nil { - t.Fatal(err) - } cache.Write(&Token{ AccessToken: "abc123", diff --git a/oauth2.go b/oauth2.go index 8a6e39f..62187d5 100644 --- a/oauth2.go +++ b/oauth2.go @@ -188,6 +188,15 @@ func (c *Config) NewTransportWithCode(exchangeCode string) (Transport, error) { return NewAuthorizedTransport(c, token), nil } +func (c *Config) NewTransportWithCache(cache Cache) (Transport, error) { + token, err := cache.Read() + if err != nil { + return nil, err + } + c.cache = cache + return NewAuthorizedTransport(c, token), nil +} + // Exchange exchanges the exchange code with the OAuth 2.0 provider // to retrieve a new access token. func (c *Config) Exchange(exchangeCode string) (*Token, error) { diff --git a/transport.go b/transport.go index 43f0036..f83d522 100644 --- a/transport.go +++ b/transport.go @@ -95,13 +95,6 @@ func NewAuthorizedTransport(fetcher TokenFetcher, token *Token) Transport { func (t *authorizedTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) { token := t.Token() - // Try to initialize the token from the cache. - if token == nil { - if c := t.fetcher.Cache(); c != nil { - token = c.Token() - } - } - if token == nil || token.Expired() { // Check if the token is refreshable. // If token is refreshable, don't return an error,