11using System ;
2+ using System . Collections . Generic ;
23using System . Diagnostics ;
4+ using System . Extensions ;
5+ using System . Net . Http . Headers ;
36using Flurl . Http ;
47using Flurl . Http . Configuration ;
8+ using net . openstack . Core ;
59using Newtonsoft . Json ;
610using OpenStack . Authentication ;
711using OpenStack . Serialization ;
@@ -14,26 +18,28 @@ namespace OpenStack
1418 /// <threadsafety static="true" instance="false"/>
1519 public static class OpenStackNet
1620 {
21+ /// <summary>
22+ /// Global configuration which affects OpenStack.NET's behavior.
23+ /// <para>Modify using <see cref="Configure"/>.</para>
24+ /// </summary>
25+ public static readonly OpenStackNetConfigurationOptions Configuration = new OpenStackNetConfigurationOptions ( ) ;
1726 private static readonly object ConfigureLock = new object ( ) ;
18- private static bool _isConfigured ;
1927
2028 /// <summary>
2129 /// Provides thread-safe accesss to OpenStack.NET's global configuration options.
2230 /// <para>
2331 /// Can only be called once at application start-up, before instantiating any OpenStack.NET objects.
2432 /// </para>
2533 /// </summary>
26- /// <param name="configureFlurl">Addtional configuration of Flurl's global settings <seealso cref="Flurl.Http.FlurlHttp.Configure"/>.</param>
27- /// <param name="configureJson">Additional configuration of Json.NET's glboal settings <seealso cref="Newtonsoft.Json.JsonConvert.DefaultSettings"/>.</param>
28- public static void Configure ( Action < FlurlHttpConfigurationOptions > configureFlurl = null , Action < JsonSerializerSettings > configureJson = null )
34+ /// <param name="configureFlurl">Addtional configuration of Flurl's global settings <seealso cref="Flurl.Http.FlurlHttp.Configure" />.</param>
35+ /// <param name="configureJson">Additional configuration of Json.NET's global settings <seealso cref="Newtonsoft.Json.JsonConvert.DefaultSettings" />.</param>
36+ /// <param name="configure">Additional configuration of OpenStack.NET's global settings.</param>
37+ public static void Configure ( Action < FlurlHttpConfigurationOptions > configureFlurl = null , Action < JsonSerializerSettings > configureJson = null , Action < OpenStackNetConfigurationOptions > configure = null )
2938 {
30- if ( _isConfigured )
31- return ;
32-
3339 lock ( ConfigureLock )
3440 {
35- if ( _isConfigured )
36- return ;
41+ if ( configure != null )
42+ configure ( Configuration ) ;
3743
3844 JsonConvert . DefaultSettings = ( ) =>
3945 {
@@ -51,20 +57,48 @@ public static void Configure(Action<FlurlHttpConfigurationOptions> configureFlur
5157 configureJson ( settings ) ;
5258 return settings ;
5359 } ;
54-
60+
5561 FlurlHttp . Configure ( c =>
5662 {
63+ // Apply the application's default settings
64+ if ( configureFlurl != null )
65+ configureFlurl ( c ) ;
66+
5767 // Apply our default settings
5868 c . HttpClientFactory = new AuthenticatedHttpClientFactory ( ) ;
59- c . AfterCall = Tracing . TraceHttpCall ;
60- c . OnError = Tracing . TraceFailedHttpCall ;
6169
62- // Apply application's default settings
63- if ( configureFlurl != null )
64- configureFlurl ( c ) ;
70+ var applicationBeforeCall = c . BeforeCall ;
71+ c . BeforeCall = call =>
72+ {
73+ SetUserAgentHeader ( call ) ;
74+ if ( applicationBeforeCall != null )
75+ applicationBeforeCall ( call ) ;
76+ } ;
77+
78+ var applicationAfterCall = c . AfterCall ;
79+ c . AfterCall = call =>
80+ {
81+ Tracing . TraceHttpCall ( call ) ;
82+ if ( applicationAfterCall != null )
83+ applicationAfterCall ( call ) ;
84+ } ;
85+
86+ var applicationOnError = c . OnError ;
87+ c . OnError = call =>
88+ {
89+ Tracing . TraceFailedHttpCall ( call ) ;
90+ if ( applicationOnError != null )
91+ applicationOnError ( call ) ;
92+ } ;
6593 } ) ;
94+ }
95+ }
6696
67- _isConfigured = true ;
97+ private static void SetUserAgentHeader ( HttpCall call )
98+ {
99+ foreach ( var userAgent in Configuration . UserAgents )
100+ {
101+ call . Request . Headers . UserAgent . Add ( userAgent ) ;
68102 }
69103 }
70104
@@ -101,4 +135,33 @@ public static void TraceHttpCall(HttpCall httpCall)
101135 }
102136 }
103137 }
138+
139+ /// <summary>
140+ /// A set of properties that affect OpenStack.NET's behavior.
141+ /// <para>Generally set via the static <see cref="OpenStack.OpenStackNet.Configure"/> method.</para>
142+ /// </summary>
143+ public class OpenStackNetConfigurationOptions
144+ {
145+ /// <summary/>
146+ protected internal OpenStackNetConfigurationOptions ( )
147+ {
148+ ResetDefaults ( ) ;
149+ }
150+
151+ /// <summary>
152+ /// Additional application specific user agents which should be set in the UserAgent header on all requests.
153+ /// </summary>
154+ public List < ProductInfoHeaderValue > UserAgents { get ; private set ; }
155+
156+ /// <summary>
157+ /// Clear all custom global options and set default values.
158+ /// </summary>
159+ public virtual void ResetDefaults ( )
160+ {
161+ UserAgents = new List < ProductInfoHeaderValue >
162+ {
163+ new ProductInfoHeaderValue ( "openstack.net" , GetType ( ) . GetAssemblyFileVersion ( ) )
164+ } ;
165+ }
166+ }
104167}
0 commit comments