1
1
/*
2
- * Copyright 2019, Optimizely
2
+ * Copyright 2019-2020 , Optimizely
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.
@@ -28,34 +28,64 @@ public class HttpProjectConfigManager : PollingProjectConfigManager
28
28
{
29
29
private string Url ;
30
30
private string LastModifiedSince = string . Empty ;
31
-
31
+ private string DatafileAccessToken = string . Empty ;
32
32
private HttpProjectConfigManager ( TimeSpan period , string url , TimeSpan blockingTimeout , bool autoUpdate , ILogger logger , IErrorHandler errorHandler )
33
33
: base ( period , blockingTimeout , autoUpdate , logger , errorHandler )
34
34
{
35
35
Url = url ;
36
36
}
37
37
38
+ private HttpProjectConfigManager ( TimeSpan period , string url , TimeSpan blockingTimeout , bool autoUpdate , ILogger logger , IErrorHandler errorHandler , string datafileAccessToken )
39
+ : this ( period , url , blockingTimeout , autoUpdate , logger , errorHandler )
40
+ {
41
+ DatafileAccessToken = datafileAccessToken ;
42
+ }
43
+
38
44
public Task OnReady ( )
39
45
{
40
46
return CompletableConfigManager . Task ;
41
47
}
42
48
43
49
#if ! NET40 && ! NET35
44
- private static System . Net . Http . HttpClient Client ;
45
- static HttpProjectConfigManager ( )
50
+ // HttpClient wrapper class which can be used to mock HttpClient for unit testing.
51
+ public class HttpClient
46
52
{
47
- Client = new System . Net . Http . HttpClient ( GetHttpClientHandler ( ) ) ;
48
- }
53
+ private System . Net . Http . HttpClient Client ;
49
54
50
- public static System . Net . Http . HttpClientHandler GetHttpClientHandler ( )
51
- {
52
- var handler = new System . Net . Http . HttpClientHandler ( ) {
53
- AutomaticDecompression = System . Net . DecompressionMethods . GZip | System . Net . DecompressionMethods . Deflate
54
- } ;
55
+ public HttpClient ( )
56
+ {
57
+ Client = new System . Net . Http . HttpClient ( GetHttpClientHandler ( ) ) ;
58
+ }
55
59
56
- return handler ;
60
+ public HttpClient ( System . Net . Http . HttpClient httpClient ) : this ( )
61
+ {
62
+ if ( httpClient != null ) {
63
+ Client = httpClient ;
64
+ }
65
+ }
66
+
67
+ public static System . Net . Http . HttpClientHandler GetHttpClientHandler ( )
68
+ {
69
+ var handler = new System . Net . Http . HttpClientHandler ( ) {
70
+ AutomaticDecompression = System . Net . DecompressionMethods . GZip | System . Net . DecompressionMethods . Deflate
71
+ } ;
72
+
73
+ return handler ;
74
+ }
75
+
76
+ public virtual Task < System . Net . Http . HttpResponseMessage > SendAsync ( System . Net . Http . HttpRequestMessage httpRequestMessage )
77
+ {
78
+ return Client . SendAsync ( httpRequestMessage ) ;
79
+ }
57
80
}
58
81
82
+ private static HttpClient Client ;
83
+
84
+ static HttpProjectConfigManager ( )
85
+ {
86
+ Client = new HttpClient ( ) ;
87
+ }
88
+
59
89
private string GetRemoteDatafileResponse ( )
60
90
{
61
91
var request = new System . Net . Http . HttpRequestMessage {
@@ -67,6 +97,10 @@ private string GetRemoteDatafileResponse()
67
97
if ( ! string . IsNullOrEmpty ( LastModifiedSince ) )
68
98
request . Headers . Add ( "If-Modified-Since" , LastModifiedSince ) ;
69
99
100
+ if ( ! string . IsNullOrEmpty ( DatafileAccessToken ) ) {
101
+ request . Headers . Authorization = new System . Net . Http . Headers . AuthenticationHeaderValue ( "Bearer" , DatafileAccessToken ) ;
102
+ }
103
+
70
104
var httpResponse = Client . SendAsync ( request ) ;
71
105
httpResponse . Wait ( ) ;
72
106
@@ -136,11 +170,12 @@ public class Builder
136
170
private readonly TimeSpan DEFAULT_PERIOD = TimeSpan . FromMinutes ( 5 ) ;
137
171
private readonly TimeSpan DEFAULT_BLOCKINGOUT_PERIOD = TimeSpan . FromSeconds ( 15 ) ;
138
172
private readonly string DEFAULT_FORMAT = "https://cdn.optimizely.com/datafiles/{0}.json" ;
139
-
173
+ private readonly string DEFAULT_AUTHENTICATED_DATAFILE_FORMAT = "https://config.optimizely.com/datafiles/auth/{0}.json" ;
140
174
private string Datafile ;
175
+ private string DatafileAccessToken ;
141
176
private string SdkKey ;
142
177
private string Url ;
143
- private string Format ;
178
+ private string Format ;
144
179
private ILogger Logger ;
145
180
private IErrorHandler ErrorHandler ;
146
181
private TimeSpan Period ;
@@ -174,6 +209,14 @@ public Builder WithSdkKey(string sdkKey)
174
209
175
210
return this ;
176
211
}
212
+ #if ! NET40 && ! NET35
213
+ public Builder WithAccessToken ( string accessToken )
214
+ {
215
+ this . DatafileAccessToken = accessToken ;
216
+
217
+ return this ;
218
+ }
219
+ #endif
177
220
178
221
public Builder WithUrl ( string url )
179
222
{
@@ -260,15 +303,18 @@ public HttpProjectConfigManager Build(bool defer)
260
303
ErrorHandler = new DefaultErrorHandler ( ) ;
261
304
262
305
if ( string . IsNullOrEmpty ( Format ) ) {
263
- Format = DEFAULT_FORMAT ;
264
- }
265
306
266
- if ( string . IsNullOrEmpty ( Url ) && string . IsNullOrEmpty ( SdkKey ) )
267
- {
268
- ErrorHandler . HandleError ( new Exception ( "SdkKey cannot be null" ) ) ;
307
+ if ( string . IsNullOrEmpty ( DatafileAccessToken ) ) {
308
+ Format = DEFAULT_FORMAT ;
309
+ } else {
310
+ Format = DEFAULT_AUTHENTICATED_DATAFILE_FORMAT ;
311
+ }
269
312
}
270
- else if ( ! string . IsNullOrEmpty ( SdkKey ) )
271
- {
313
+
314
+ if ( string . IsNullOrEmpty ( Url ) ) {
315
+ if ( string . IsNullOrEmpty ( SdkKey ) ) {
316
+ ErrorHandler . HandleError ( new Exception ( "SdkKey cannot be null" ) ) ;
317
+ }
272
318
Url = string . Format ( Format , SdkKey ) ;
273
319
}
274
320
@@ -290,7 +336,7 @@ public HttpProjectConfigManager Build(bool defer)
290
336
}
291
337
292
338
293
- configManager = new HttpProjectConfigManager ( Period , Url , BlockingTimeoutSpan , AutoUpdate , Logger , ErrorHandler ) ;
339
+ configManager = new HttpProjectConfigManager ( Period , Url , BlockingTimeoutSpan , AutoUpdate , Logger , ErrorHandler , DatafileAccessToken ) ;
294
340
295
341
if ( Datafile != null )
296
342
{
0 commit comments