@@ -10,36 +10,52 @@ import (
1010 "golang.org/x/oauth2/clientcredentials"
1111
1212 "github.com/plgd-dev/kit/log"
13- "github.com/plgd-dev/kit/net/http/transport"
1413 "golang.org/x/oauth2"
1514)
1615
1716// Manager holds certificates from filesystem watched for changes
1817type Manager struct {
19- mutex sync.Mutex
20- config clientcredentials.Config
21- tlsCfg * tls.Config
22- requestTimeout time.Duration
23- token * oauth2.Token
24- tokenErr error
25- doneWg sync.WaitGroup
26- done chan struct {}
18+ mutex sync.Mutex
19+ config clientcredentials.Config
20+ tlsCfg * tls.Config
21+ requestTimeout time.Duration
22+ tickFrequency time.Duration
23+ startRefreshToken time.Time
24+ token * oauth2.Token
25+ httpClient * http.Client
26+ tokenErr error
27+ doneWg sync.WaitGroup
28+ done chan struct {}
2729}
2830
2931// NewManagerFromConfiguration creates a new oauth manager which refreshing token.
3032func NewManagerFromConfiguration (config Config , tlsCfg * tls.Config ) (* Manager , error ) {
3133 cfg := config .ToClientCrendtials ()
32- token , err := getToken (cfg , tlsCfg , config .RequestTimeout )
34+ t := http .DefaultTransport .(* http.Transport ).Clone ()
35+ t .MaxIdleConns = 1
36+ t .MaxConnsPerHost = 1
37+ t .MaxIdleConnsPerHost = 1
38+ t .IdleConnTimeout = time .Second * 30
39+ t .TLSClientConfig = tlsCfg
40+ httpClient := & http.Client {
41+ Transport : t ,
42+ Timeout : config .RequestTimeout ,
43+ }
44+ token , startRefreshToken , err := getToken (cfg , httpClient , config .RequestTimeout )
3345 if err != nil {
3446 return nil , err
3547 }
36- mgr := & Manager {
37- config : cfg ,
38- token : token ,
39- tlsCfg : tlsCfg ,
4048
41- requestTimeout : config .RequestTimeout ,
42- done : make (chan struct {}),
49+ mgr := & Manager {
50+ config : cfg ,
51+ token : token ,
52+ tlsCfg : tlsCfg ,
53+ startRefreshToken : startRefreshToken ,
54+ requestTimeout : config .RequestTimeout ,
55+ httpClient : httpClient ,
56+ tickFrequency : config .TickFrequency ,
57+
58+ done : make (chan struct {}),
4359 }
4460 mgr .doneWg .Add (1 )
4561
@@ -63,48 +79,50 @@ func (a *Manager) Close() {
6379 }
6480}
6581
66- func (a * Manager ) nextRenewal () time.Duration {
67- t , _ := a .GetToken (context .Background ())
68- now := time .Now ()
69- lifetime := t .Expiry .Sub (now ) * 2 / 3
70- if lifetime < a .requestTimeout {
71- lifetime = a .requestTimeout
72- }
73- return lifetime
82+ func (a * Manager ) wantToRefresh () bool {
83+ return time .Now ().After (a .startRefreshToken )
7484}
7585
76- func getToken (cfg clientcredentials.Config , tlsCfg * tls. Config , requestTimeout time.Duration ) (* oauth2.Token , error ) {
86+ func getToken (cfg clientcredentials.Config , httpClient * http. Client , requestTimeout time.Duration ) (* oauth2.Token , time. Time , error ) {
7787 ctx , cancel := context .WithTimeout (context .Background (), requestTimeout )
7888 defer cancel ()
7989
80- t := transport .NewDefaultTransport ()
81- t .TLSClientConfig = tlsCfg
82- httpClient := & http.Client {Transport : t }
8390 ctx = context .WithValue (ctx , oauth2 .HTTPClient , httpClient )
8491
85- return cfg .Token (ctx )
92+ token , err := cfg .Token (ctx )
93+ var startRefreshToken time.Time
94+ if err == nil {
95+ now := time .Now ()
96+ startRefreshToken = now .Add (token .Expiry .Sub (now ) * 2 / 3 )
97+ }
98+ return token , startRefreshToken , err
8699}
87100
88101func (a * Manager ) refreshToken () {
89- token , err := getToken (a .config , a .tlsCfg , a .requestTimeout )
102+ token , startRefreshToken , err := getToken (a .config , a .httpClient , a .requestTimeout )
90103 if err != nil {
91104 log .Errorf ("cannot refresh token: %v" , err )
92105 }
93106 a .mutex .Lock ()
94107 defer a .mutex .Unlock ()
95108 a .token = token
96109 a .tokenErr = err
110+ a .startRefreshToken = startRefreshToken
97111}
98112
99113func (a * Manager ) watchToken () {
100114 defer a .doneWg .Done ()
115+ t := time .NewTicker (a .tickFrequency )
116+ defer t .Stop ()
117+
101118 for {
102- nextRenewal := a .nextRenewal ()
103119 select {
104120 case <- a .done :
105121 return
106- case <- time .After (nextRenewal ):
107- a .refreshToken ()
122+ case <- t .C :
123+ if a .wantToRefresh () {
124+ a .refreshToken ()
125+ }
108126 }
109127 }
110128}
0 commit comments