1
1
/****************************************************************************
2
- * Copyright 2019, Optimizely, Inc. and contributors *
2
+ * Copyright 2019-2020 , Optimizely, Inc. and contributors *
3
3
* *
4
4
* Licensed under the Apache License, Version 2.0 (the "License"); *
5
5
* you may not use this file except in compliance with the License. *
@@ -42,9 +42,12 @@ const ModifiedSince = "If-Modified-Since"
42
42
// LastModified header key for response
43
43
const LastModified = "Last-Modified"
44
44
45
- // DatafileURLTemplate is used to construct the endpoint for retrieving the datafile from the CDN
45
+ // DatafileURLTemplate is used to construct the endpoint for retrieving regular datafile from the CDN
46
46
const DatafileURLTemplate = "https://cdn.optimizely.com/datafiles/%s.json"
47
47
48
+ // AuthDatafileURLTemplate is used to construct the endpoint for retrieving authenticated datafile from the CDN
49
+ const AuthDatafileURLTemplate = "https://config.optimizely.com/datafiles/auth/%s.json"
50
+
48
51
// Err403Forbidden is 403Forbidden specific error
49
52
var Err403Forbidden = errors .New ("unable to fetch fresh datafile (consider rechecking SDK key), status code: 403 Forbidden" )
50
53
@@ -58,7 +61,8 @@ type PollingProjectConfigManager struct {
58
61
pollingInterval time.Duration
59
62
requester utils.Requester
60
63
sdkKey string
61
- logger logging.OptimizelyLogProducer
64
+ logger logging.OptimizelyLogProducer
65
+ datafileAccessToken string
62
66
63
67
configLock sync.RWMutex
64
68
err error
@@ -97,6 +101,13 @@ func WithInitialDatafile(datafile []byte) OptionFunc {
97
101
}
98
102
}
99
103
104
+ // WithDatafileAccessToken is an optional function, sets a passed datafile access token
105
+ func WithDatafileAccessToken (datafileAccessToken string ) OptionFunc {
106
+ return func (p * PollingProjectConfigManager ) {
107
+ p .datafileAccessToken = datafileAccessToken
108
+ }
109
+ }
110
+
100
111
// SyncConfig downloads datafile and updates projectConfig
101
112
func (cm * PollingProjectConfigManager ) SyncConfig () {
102
113
var e error
@@ -169,6 +180,10 @@ func (cm *PollingProjectConfigManager) SyncConfig() {
169
180
170
181
// Start starts the polling
171
182
func (cm * PollingProjectConfigManager ) Start (ctx context.Context ) {
183
+ if cm .pollingInterval <= 0 {
184
+ cm .logger .Info ("Polling Config Manager Disabled" )
185
+ return
186
+ }
172
187
cm .logger .Debug ("Polling Config Manager Initiated" )
173
188
t := time .NewTicker (cm .pollingInterval )
174
189
for {
@@ -182,48 +197,59 @@ func (cm *PollingProjectConfigManager) Start(ctx context.Context) {
182
197
}
183
198
}
184
199
185
- // NewPollingProjectConfigManager returns an instance of the polling config manager with the customized configuration
186
- func NewPollingProjectConfigManager (sdkKey string , pollingMangerOptions ... OptionFunc ) * PollingProjectConfigManager {
200
+ func (cm * PollingProjectConfigManager ) setAuthHeaderIfDatafileAccessTokenPresent () {
201
+ if cm .datafileAccessToken != "" {
202
+ headers := []utils.Header {{Name : "Content-Type" , Value : "application/json" }, {Name : "Accept" , Value : "application/json" }}
203
+ headers = append (headers , utils.Header {Name : "Authorization" , Value : "Bearer " + cm .datafileAccessToken })
204
+ cm .requester = utils .NewHTTPRequester (logging .GetLogger (cm .sdkKey , "HTTPRequester" ), utils .Headers (headers ... ))
205
+ }
206
+ }
187
207
208
+ func newConfigManager (sdkKey string , logger logging.OptimizelyLogProducer , configOptions ... OptionFunc ) * PollingProjectConfigManager {
188
209
pollingProjectConfigManager := PollingProjectConfigManager {
189
- notificationCenter : registry .GetNotificationCenter (sdkKey ),
190
- pollingInterval : DefaultPollingInterval ,
191
- requester : utils .NewHTTPRequester (logging .GetLogger (sdkKey , "HTTPRequester" )),
192
- datafileURLTemplate : DatafileURLTemplate ,
193
- sdkKey : sdkKey ,
194
- logger : logging .GetLogger (sdkKey , "PollingProjectConfigManager" ),
210
+ notificationCenter : registry .GetNotificationCenter (sdkKey ),
211
+ pollingInterval : DefaultPollingInterval ,
212
+ requester : utils .NewHTTPRequester (logging .GetLogger (sdkKey , "HTTPRequester" )),
213
+ sdkKey : sdkKey ,
214
+ logger : logger ,
195
215
}
196
216
197
- for _ , opt := range pollingMangerOptions {
217
+ for _ , opt := range configOptions {
198
218
opt (& pollingProjectConfigManager )
199
219
}
200
220
221
+ if pollingProjectConfigManager .datafileURLTemplate == "" {
222
+ if pollingProjectConfigManager .datafileAccessToken != "" {
223
+ pollingProjectConfigManager .datafileURLTemplate = AuthDatafileURLTemplate
224
+ } else {
225
+ pollingProjectConfigManager .datafileURLTemplate = DatafileURLTemplate
226
+ }
227
+ }
228
+ pollingProjectConfigManager .setAuthHeaderIfDatafileAccessTokenPresent ()
229
+ return & pollingProjectConfigManager
230
+ }
231
+
232
+ // NewPollingProjectConfigManager returns an instance of the polling config manager with the customized configuration
233
+ func NewPollingProjectConfigManager (sdkKey string , pollingMangerOptions ... OptionFunc ) * PollingProjectConfigManager {
234
+
235
+ pollingProjectConfigManager := newConfigManager (sdkKey , logging .GetLogger (sdkKey , "PollingProjectConfigManager" ), pollingMangerOptions ... )
236
+
201
237
if len (pollingProjectConfigManager .initDatafile ) > 0 {
202
238
pollingProjectConfigManager .setInitialDatafile (pollingProjectConfigManager .initDatafile )
203
239
} else {
204
240
pollingProjectConfigManager .SyncConfig () // initial poll
205
241
}
206
- return & pollingProjectConfigManager
242
+ return pollingProjectConfigManager
207
243
}
208
244
209
245
// NewAsyncPollingProjectConfigManager returns an instance of the async polling config manager with the customized configuration
210
246
func NewAsyncPollingProjectConfigManager (sdkKey string , pollingMangerOptions ... OptionFunc ) * PollingProjectConfigManager {
211
247
212
- pollingProjectConfigManager := PollingProjectConfigManager {
213
- notificationCenter : registry .GetNotificationCenter (sdkKey ),
214
- pollingInterval : DefaultPollingInterval ,
215
- requester : utils .NewHTTPRequester (logging .GetLogger (sdkKey , "HTTPRequester" )),
216
- datafileURLTemplate : DatafileURLTemplate ,
217
- sdkKey : sdkKey ,
218
- logger : logging .GetLogger (sdkKey , "PollingProjectConfigManager" ),
219
- }
220
-
221
- for _ , opt := range pollingMangerOptions {
222
- opt (& pollingProjectConfigManager )
248
+ pollingProjectConfigManager := newConfigManager (sdkKey , logging .GetLogger (sdkKey , "PollingProjectConfigManager" ), pollingMangerOptions ... )
249
+ if len (pollingProjectConfigManager .initDatafile ) > 0 {
250
+ pollingProjectConfigManager .setInitialDatafile (pollingProjectConfigManager .initDatafile )
223
251
}
224
-
225
- pollingProjectConfigManager .setInitialDatafile (pollingProjectConfigManager .initDatafile )
226
- return & pollingProjectConfigManager
252
+ return pollingProjectConfigManager
227
253
}
228
254
229
255
// GetConfig returns the project config
0 commit comments