Merge pull request #11 from proppy/master

remove cache
This commit is contained in:
Burcu Dogan 2014-07-09 14:08:38 -07:00
commit 26b7d82d9d
11 changed files with 10 additions and 262 deletions

View File

@ -1,55 +0,0 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package oauth2
import (
"encoding/json"
"io/ioutil"
"os"
)
// Cache represents a token cacher.
type Cache interface {
// Reads a cached token. It may return nil if none is cached.
Read() (*Token, error)
// Write writes a token to the cache.
Write(*Token) error
}
// NewFileCache creates a new file cache.
func NewFileCache(filename string) (cache *FileCache) {
return &FileCache{filename: filename}
}
// FileCache represents a file based token cacher.
type FileCache struct {
filename string
}
// Read reads the token from the cache file. If there exists no cache
// file, it returns nil for the token.
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.
func (f *FileCache) Write(token *Token) error {
data, err := json.Marshal(token)
if err == nil {
err = ioutil.WriteFile(f.filename, data, 0644)
}
return err
}

View File

@ -1,74 +0,0 @@
// Copyright 2014 The oauth2 Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package oauth2
import (
"io/ioutil"
"path"
"testing"
)
var tokenBody = `{"access_token":"abc123","token_type":"Bearer","refresh_token":"def789","expiry":"0001-01-01T00:00:00Z"}`
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 token != nil {
t.Fatalf("Token should be nil, but found %v", token)
}
}
func TestNewFileCache(t *testing.T) {
f, err := ioutil.TempFile("", "")
if err != nil {
t.Fatal(err)
}
_, err = f.WriteString(tokenBody)
if err != nil {
t.Fatal(err)
}
cache := NewFileCache(f.Name())
token, err := cache.Read()
if err != nil {
t.Fatal(err)
}
if token.AccessToken != "abc123" {
t.Fatalf("Cached access token is %v, expected to be abc123", token.AccessToken)
}
if token.RefreshToken != "def789" {
t.Fatalf("Cached refresh token is %v, expected to be def789", token.RefreshToken)
}
}
func TestFileCacheWrite(t *testing.T) {
dirName, err := ioutil.TempDir("", "")
if err != nil {
t.Fatal(err)
}
cache := NewFileCache(path.Join(dirName, "cache-file"))
err = cache.Write(&Token{
AccessToken: "abc123",
TokenType: "Bearer",
RefreshToken: "def789",
})
if err != nil {
t.Errorf("Cache write should have been succeeded succesfully, recieved %v", err)
}
data, err := ioutil.ReadFile(cache.filename)
if err != nil {
t.Fatal(err)
}
if string(data) != tokenBody {
t.Fatalf("Written token is different than the expected, %v is found", data)
}
}

View File

@ -51,23 +51,6 @@ func Example_config() {
// start making authenticated requests. // start making authenticated requests.
client := http.Client{Transport: t} client := http.Client{Transport: t}
client.Get("...") client.Get("...")
// Alternatively, you can initiate a new transport
// with tokens from a cache.
cache := oauth2.NewFileCache("/path/to/file")
// NewTransportWithCache will try to read the cached
// token, if any error occurs, it returns the error.
// If a token is available at the cache, initiates
// a new transport authorized and authenticated with
// the read token. If token expires, and a new access
// token is retrieved, it writes the newly fetched
// token to the cache.
t, err = conf.NewTransportWithCache(cache)
if err != nil {
log.Fatal(err)
}
client = http.Client{Transport: t}
client.Get("...")
} }
func Example_jWTConfig() { func Example_jWTConfig() {
@ -95,18 +78,4 @@ func Example_jWTConfig() {
// request will be made on the behalf of user@example.com. // request will be made on the behalf of user@example.com.
client = http.Client{Transport: conf.NewTransportWithUser("user@example.com")} client = http.Client{Transport: conf.NewTransportWithUser("user@example.com")}
client.Get("...") client.Get("...")
// Alternatively you can iniate a transport with
// a token read from the cache.
// If the existing access token expires, and a new access token is
// retrieved, the newly fetched token will be written to the cache.
cache := oauth2.NewFileCache("/path/to/file")
t, err := conf.NewTransportWithCache(cache)
if err != nil {
log.Fatal(err)
}
client = http.Client{Transport: t}
// The following request will be authorized by the token
// retrieved from the cache.
client.Get("...")
} }

View File

@ -5,8 +5,9 @@ package google
import ( import (
"strings" "strings"
"appengine"
"github.com/golang/oauth2" "github.com/golang/oauth2"
"appengine"
) )
// AppEngineConfig represents a configuration for an // AppEngineConfig represents a configuration for an
@ -28,12 +29,6 @@ func (c *AppEngineConfig) NewTransport() oauth2.Transport {
return oauth2.NewAuthorizedTransport(c, nil) return oauth2.NewAuthorizedTransport(c, nil)
} }
// NewTransport returns a token-caching transport that authorizes
// the requests with the application's service account.
func (c *AppEngineConfig) NewTransportWithCache(cache oauth2.Cache) (oauth2.Transport, error) {
return oauth2.NewAuthorizedTransportWithCache(c, cache)
}
// FetchToken fetches a new access token for the provided scopes. // FetchToken fetches a new access token for the provided scopes.
func (c *AppEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) { func (c *AppEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) {
token, expiry, err := appengine.AccessToken(c.context, strings.Join(c.scopes, " ")) token, expiry, err := appengine.AccessToken(c.context, strings.Join(c.scopes, " "))

View File

@ -14,7 +14,6 @@ import (
type AppEngineConfig struct { type AppEngineConfig struct {
context appengine.Context context appengine.Context
scopes []string scopes []string
cache oauth2.Cache
} }
// NewAppEngineConfig creates a new AppEngineConfig for the // NewAppEngineConfig creates a new AppEngineConfig for the
@ -29,12 +28,6 @@ func (c *AppEngineConfig) NewTransport() oauth2.Transport {
return oauth2.NewAuthorizedTransport(c, nil) return oauth2.NewAuthorizedTransport(c, nil)
} }
// NewTransport returns a token-caching transport that authorizes
// the requests with the application's service account.
func (c *AppEngineConfig) NewTransportWithCache(cache oauth2.Cache) (oauth2.Transport, error) {
return oauth2.NewAuthorizedTransportWithCache(c, cache)
}
// FetchToken fetches a new access token for the provided scopes. // FetchToken fetches a new access token for the provided scopes.
func (c *AppEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) { func (c *AppEngineConfig) FetchToken(existing *oauth2.Token) (*oauth2.Token, error) {
token, expiry, err := appengine.AccessToken(c.context, strings.Join(c.scopes, " ")) token, expiry, err := appengine.AccessToken(c.context, strings.Join(c.scopes, " "))

View File

@ -45,23 +45,6 @@ func Example_webServer() {
} }
client := http.Client{Transport: t} client := http.Client{Transport: t}
client.Get("...") client.Get("...")
// Alternatively you can initiate a new transport
// with a token from a cache.
cache := oauth2.NewFileCache("/path/to/file")
// NewTransportWithCache will try to read the cached
// token, if any error occurs, it returns the error.
// If a token is available at the cache, initiates
// a new transport authorized and authenticated with
// the read token. If token expires, and a new access
// token is retrieved, it writes the newly fetched
// token to the cache.
t, err = config.NewTransportWithCache(cache)
if err != nil {
log.Fatal(err)
}
client = http.Client{Transport: t}
client.Get("...")
} }
func Example_serviceAccounts() { func Example_serviceAccounts() {
@ -92,20 +75,6 @@ func Example_serviceAccounts() {
// request will be made on the behalf of user@example.com. // request will be made on the behalf of user@example.com.
client = http.Client{Transport: config.NewTransportWithUser("user@example.com")} client = http.Client{Transport: config.NewTransportWithUser("user@example.com")}
client.Get("...") client.Get("...")
// Alternatively you can iniate a transport with
// a token read from the cache.
// If the existing access token expires, and a new access token is
// retrieved, the newly fetched token will be written to the cache.
cache := oauth2.NewFileCache("/path/to/file")
t, err := config.NewTransportWithCache(cache)
if err != nil {
log.Fatal(err)
}
client = http.Client{Transport: t}
// The following request will be authorized by the token
// retrieved from the cache.
client.Get("...")
} }
func Example_appEngine() { func Example_appEngine() {

7
jwt.go
View File

@ -70,13 +70,6 @@ func (c *JWTConfig) NewTransportWithUser(user string) Transport {
return NewAuthorizedTransport(c, &Token{Subject: user}) return NewAuthorizedTransport(c, &Token{Subject: user})
} }
// NewTransportWithCache initializes a transport by reading the initial
// token from the provided cache. If a token refreshing occurs, it
// writes the newly fetched token back to the cache.
func (c *JWTConfig) NewTransportWithCache(cache Cache) (Transport, error) {
return NewAuthorizedTransportWithCache(c, cache)
}
// fetchToken retrieves a new access token and updates the existing token // fetchToken retrieves a new access token and updates the existing token
// with the newly fetched credentials. // with the newly fetched credentials.
func (c *JWTConfig) FetchToken(existing *Token) (token *Token, err error) { func (c *JWTConfig) FetchToken(existing *Token) (token *Token, err error) {

View File

@ -153,13 +153,6 @@ func (c *Config) NewTransportWithCode(exchangeCode string) (Transport, error) {
return NewAuthorizedTransport(c, token), nil return NewAuthorizedTransport(c, token), nil
} }
// NewTransportWithCache initializes a transport by reading the initial
// token from the provided cache. If a token refreshing occurs, it
// writes the newly fetched token back to the cache.
func (c *Config) NewTransportWithCache(cache Cache) (Transport, error) {
return NewAuthorizedTransportWithCache(c, cache)
}
// FetchToken retrieves a new access token and updates the existing token // FetchToken retrieves a new access token and updates the existing token
// with the newly fetched credentials. If existing token doesn't // with the newly fetched credentials. If existing token doesn't
// contain a refresh token, it returns an error. // contain a refresh token, it returns an error.

View File

@ -62,7 +62,7 @@ func TestExchangePayload(t *testing.T) {
return nil, errors.New("no response") return nil, errors.New("no response")
}, },
} }
conf.Exchange("exchange-code") conf.exchange("exchange-code")
} }
func TestExchangingTransport(t *testing.T) { func TestExchangingTransport(t *testing.T) {

View File

@ -76,9 +76,6 @@ type Transport interface {
} }
type authorizedTransport struct { type authorizedTransport struct {
// Cache to persist changes to the token that
// authorizes the current transport.
cache Cache
fetcher TokenFetcher fetcher TokenFetcher
token *Token token *Token
@ -93,19 +90,6 @@ func NewAuthorizedTransport(fetcher TokenFetcher, token *Token) Transport {
return &authorizedTransport{fetcher: fetcher, token: token} return &authorizedTransport{fetcher: fetcher, token: token}
} }
// NewAuthorizedTransportWithCache creates a new transport that uses
// the provided token fetcher and cache. Before constructing the new
// transport, it will try to read from the cache to see if there
// is an existing token.
func NewAuthorizedTransportWithCache(fetcher TokenFetcher, cache Cache) (transport Transport, err error) {
var token *Token
if token, err = cache.Read(); err != nil {
return
}
transport = &authorizedTransport{fetcher: fetcher, cache: cache, token: token}
return
}
// RoundTrip authorizes the request with the existing token. // RoundTrip authorizes the request with the existing token.
// If token is expired, tries to refresh/fetch a new token. // If token is expired, tries to refresh/fetch a new token.
func (t *authorizedTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) { func (t *authorizedTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
@ -176,9 +160,6 @@ func (t *authorizedTransport) RefreshToken() error {
} }
t.token = token t.token = token
if t.cache != nil {
return t.cache.Write(token)
}
return nil return nil
} }

View File

@ -7,17 +7,6 @@ import (
"time" "time"
) )
type mockCache struct{ token *Token }
func (m *mockCache) Read() (token *Token, err error) {
return m.token, nil
}
func (m *mockCache) Write(token *Token) error {
m.token = token
return nil
}
type mockTokenFetcher struct{ token *Token } type mockTokenFetcher struct{ token *Token }
func (f *mockTokenFetcher) FetchToken(existing *Token) (*Token, error) { func (f *mockTokenFetcher) FetchToken(existing *Token) (*Token, error) {
@ -25,13 +14,10 @@ func (f *mockTokenFetcher) FetchToken(existing *Token) (*Token, error) {
} }
func TestInitialTokenRead(t *testing.T) { func TestInitialTokenRead(t *testing.T) {
cache := &mockCache{token: &Token{ tr := NewAuthorizedTransport(nil, &Token{AccessToken: "abc"})
AccessToken: "abc",
}}
tr, _ := NewAuthorizedTransportWithCache(nil, cache)
server := newMockServer(func(w http.ResponseWriter, r *http.Request) { server := newMockServer(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Authorization") != "Bearer abc" { if r.Header.Get("Authorization") != "Bearer abc" {
t.Errorf("Transport doesn't read the token initially from the cache") t.Errorf("Transport doesn't set the Authorization header from the initial token")
} }
}) })
defer server.Close() defer server.Close()
@ -39,26 +25,24 @@ func TestInitialTokenRead(t *testing.T) {
client.Get(server.URL) client.Get(server.URL)
} }
func TestTokenWrite(t *testing.T) { func TestTokenFetch(t *testing.T) {
fetcher := &mockTokenFetcher{ fetcher := &mockTokenFetcher{
token: &Token{ token: &Token{
AccessToken: "abc", AccessToken: "abc",
}, },
} }
// cache with expired token tr := NewAuthorizedTransport(fetcher, nil)
cache := &mockCache{token: &Token{}}
tr, _ := NewAuthorizedTransportWithCache(fetcher, cache)
server := newMockServer(func(w http.ResponseWriter, r *http.Request) { server := newMockServer(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Authorization") != "Bearer abc" { if r.Header.Get("Authorization") != "Bearer abc" {
t.Errorf("Transport doesn't read the token initially from the cache") t.Errorf("Transport doesn't set the Authorization header from the fetched token")
} }
}) })
defer server.Close() defer server.Close()
client := http.Client{Transport: tr} client := http.Client{Transport: tr}
client.Get(server.URL) client.Get(server.URL)
if cache.token.AccessToken != "abc" { if tr.Token().AccessToken != "abc" {
t.Errorf("New token is not cached, found %v", cache.token) t.Errorf("New token is not set, found %v", tr.Token())
} }
} }