Skip to content

Commit 6128a9e

Browse files
committed
Merge pull request #482 from sharwell/fix-478
2 parents f4639d3 + b7e4249 commit 6128a9e

File tree

3 files changed

+106
-17
lines changed

3 files changed

+106
-17
lines changed

src/corelib/Core/UserAgentGenerator.cs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Diagnostics;
3+
using System.Reflection;
24

35
namespace net.openstack.Core
46
{
@@ -8,17 +10,27 @@ namespace net.openstack.Core
810
/// <threadsafety static="true" instance="false"/>
911
public static class UserAgentGenerator
1012
{
11-
private static readonly Version _currentVersion = typeof(UserAgentGenerator).Assembly.GetName().Version;
12-
private static readonly string _userAgent = string.Format("openstack.net/{0}", _currentVersion);
13-
1413
/// <summary>
1514
/// Gets the User-Agent value for this SDK.
1615
/// </summary>
17-
public static string UserAgent
16+
public static readonly string UserAgent = GetUserAgent();
17+
18+
private static string GetUserAgent()
1819
{
19-
get
20+
return string.Format("openstack.net/{0}", GetVersion());
21+
}
22+
23+
private static string GetVersion()
24+
{
25+
Assembly sdkAssembly = typeof(UserAgentGenerator).Assembly;
26+
try
27+
{
28+
var fileVersionInfo = FileVersionInfo.GetVersionInfo(sdkAssembly.Location);
29+
return fileVersionInfo.FileVersion;
30+
}
31+
catch
2032
{
21-
return _userAgent;
33+
return sdkAssembly.GetName().Version.ToString();
2234
}
2335
}
2436
}

src/corelib/Providers/Rackspace/ProviderBase`1.cs

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ public abstract class ProviderBase<TProvider>
6666
/// </summary>
6767
private IBackoffPolicy _backoffPolicy;
6868

69+
/// <summary>
70+
/// This is the backing field for the <see cref="ApplicationUserAgent"/> property.
71+
/// </summary>
72+
private string _applicationUserAgent;
73+
6974
/// <summary>
7075
/// Initializes a new instance of the <see cref="ProviderBase{TProvider}"/> class using
7176
/// the specified default identity, default region, identity provider, and REST service
@@ -166,6 +171,36 @@ public IBackoffPolicy BackoffPolicy
166171
}
167172
}
168173

174+
/// <summary>
175+
/// Gets or sets the application-specific user agent for the provider instance.
176+
/// </summary>
177+
/// <remarks>
178+
/// <para>This value is used for determining the <see cref="DefaultUserAgent"/> value. The documentation for
179+
/// that property includes specific information.</para>
180+
/// <para>The default value is <see langword="null"/>.</para>
181+
/// </remarks>
182+
/// <value>
183+
/// <para>The application-specific user agent, as a string. This string should be a valid
184+
/// <strong>User-Agent</strong> header value according to RFC 7231.</para>
185+
/// <para>-or-</para>
186+
/// <para><see langword="null"/> (or <see cref="string.Empty"/>) if the provider should not include an
187+
/// application-specific user agent in HTTP requests, or if the user agent is customized in another manner (such
188+
/// as overriding the <see cref="BuildDefaultRequestSettings"/> method.</para>
189+
/// </value>
190+
/// <preliminary/>
191+
public string ApplicationUserAgent
192+
{
193+
get
194+
{
195+
return _applicationUserAgent;
196+
}
197+
198+
set
199+
{
200+
_applicationUserAgent = value;
201+
}
202+
}
203+
169204
/// <summary>
170205
/// Gets the default back-off policy for the current provider.
171206
/// </summary>
@@ -182,6 +217,32 @@ protected virtual IBackoffPolicy DefaultBackoffPolicy
182217
}
183218
}
184219

220+
/// <summary>
221+
/// Gets the default value for the <strong>User-Agent</strong> header for HTTP requests sent by this provider.
222+
/// </summary>
223+
/// <remarks>
224+
/// <para>If the <see cref="ApplicationUserAgent"/> property is not set, this property simply returns
225+
/// <see cref="UserAgentGenerator.UserAgent"/>.</para>
226+
/// <para>If the <see cref="ApplicationUserAgent"/> property is set, this property returns a two-part user agent
227+
/// starting with the <see cref="ApplicationUserAgent"/> value, followed by the
228+
/// <see cref="UserAgentGenerator.UserAgent"/> value.</para>
229+
/// </remarks>
230+
/// <value>
231+
/// The default value for the <strong>User-Agent</strong> header for HTTP requests sent by this provider.
232+
/// </value>
233+
protected string DefaultUserAgent
234+
{
235+
get
236+
{
237+
string userAgent = UserAgentGenerator.UserAgent;
238+
string applicationUserAgent = ApplicationUserAgent;
239+
if (!string.IsNullOrEmpty(applicationUserAgent))
240+
return applicationUserAgent + " " + userAgent;
241+
242+
return userAgent;
243+
}
244+
}
245+
185246
/// <summary>
186247
/// Execute a REST request with an <see cref="object"/> body and strongly-typed result.
187248
/// </summary>
@@ -439,7 +500,7 @@ private T ExecuteRESTRequest<T>(CloudIdentity identity, Uri absoluteUri, HttpMet
439500
}
440501

441502
if (string.IsNullOrEmpty(requestSettings.UserAgent))
442-
requestSettings.UserAgent = UserAgentGenerator.UserAgent;
503+
requestSettings.UserAgent = DefaultUserAgent;
443504

444505
var response = callback(absoluteUri, method, bodyStr, headers, queryStringParameter, requestSettings);
445506

@@ -536,7 +597,7 @@ protected Response StreamRESTRequest(CloudIdentity identity, Uri absoluteUri, Ht
536597
headers["X-Auth-Token"] = IdentityProvider.GetToken(identity, isRetry).Id;
537598

538599
if (string.IsNullOrEmpty(requestSettings.UserAgent))
539-
requestSettings.UserAgent = UserAgentGenerator.UserAgent;
600+
requestSettings.UserAgent = DefaultUserAgent;
540601

541602
long? initialPosition;
542603
try
@@ -609,7 +670,7 @@ protected Response StreamRESTRequest(CloudIdentity identity, Uri absoluteUri, Ht
609670
/// <item>The <see cref="RequestSettings.RetryCount"/> is 0.</item>
610671
/// <item>The <see cref="RequestSettings.RetryDelay"/> is 200 milliseconds.</item>
611672
/// <item>The <see cref="RequestSettings.Non200SuccessCodes"/> contains <see cref="HttpStatusCode.Unauthorized"/> and <see cref="HttpStatusCode.Conflict"/>, along with the values in <paramref name="non200SuccessCodes"/> (if any).</item>
612-
/// <item>The <see cref="RequestSettings.UserAgent"/> is set to <see cref="UserAgentGenerator.UserAgent"/>.</item>
673+
/// <item>The <see cref="RequestSettings.UserAgent"/> is set to <see cref="DefaultUserAgent"/>.</item>
613674
/// <item>The <see cref="RequestSettings.AllowZeroContentLength"/> is set to <see langword="true"/>.</item>
614675
/// <item>The <see cref="RequestSettings.ConnectionLimit"/> is set to <see cref="ConnectionLimit"/>.</item>
615676
/// <item>Other properties are set to the default values for <see cref="JsonRequestSettings"/>.</item>
@@ -630,7 +691,7 @@ protected virtual RequestSettings BuildDefaultRequestSettings(IEnumerable<HttpSt
630691
RetryCount = 0,
631692
RetryDelay = TimeSpan.FromMilliseconds(200),
632693
Non200SuccessCodes = non200SuccessCodesAggregate,
633-
UserAgent = UserAgentGenerator.UserAgent,
694+
UserAgent = DefaultUserAgent,
634695
AllowZeroContentLength = true,
635696
ConnectionLimit = ConnectionLimit,
636697
};
@@ -1045,7 +1106,7 @@ protected virtual byte[] EncodeRequestBodyImpl<TBody>(HttpWebRequest request, TB
10451106
/// </item>
10461107
/// <item>
10471108
/// <description><see cref="HttpWebRequest.UserAgent"/></description>
1048-
/// <description><see cref="UserAgentGenerator.UserAgent"/></description>
1109+
/// <description><see cref="DefaultUserAgent"/></description>
10491110
/// </item>
10501111
/// <item>
10511112
/// <description><see cref="WebRequest.Timeout"/></description>
@@ -1085,7 +1146,7 @@ protected virtual HttpWebRequest PrepareRequestImpl(HttpMethod method, IdentityT
10851146
request.Method = method.ToString().ToUpperInvariant();
10861147
request.Accept = JsonRequestSettings.JsonContentType;
10871148
request.Headers["X-Auth-Token"] = identityToken.Id;
1088-
request.UserAgent = UserAgentGenerator.UserAgent;
1149+
request.UserAgent = DefaultUserAgent;
10891150
request.Timeout = (int)TimeSpan.FromSeconds(14400).TotalMilliseconds;
10901151
if (ConnectionLimit.HasValue)
10911152
request.ServicePoint.ConnectionLimit = ConnectionLimit.Value;

src/testing/integration/Bootstrapper.cs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,27 +55,43 @@ public static IIdentityProvider CreateIdentityProvider()
5555

5656
public static IIdentityProvider CreateIdentityProvider(CloudIdentity identity)
5757
{
58-
return new CloudIdentityProvider(identity);
58+
var provider = new CloudIdentityProvider(identity);
59+
SetUserAgent(provider);
60+
return provider;
5961
}
6062

6163
public static IComputeProvider CreateComputeProvider()
6264
{
63-
return new CloudServersProvider(Bootstrapper.Settings.TestIdentity, Bootstrapper.Settings.DefaultRegion, null, null);
65+
var provider = new CloudServersProvider(Bootstrapper.Settings.TestIdentity, Bootstrapper.Settings.DefaultRegion, CreateIdentityProvider(), null);
66+
SetUserAgent(provider);
67+
return provider;
6468
}
6569

6670
public static INetworksProvider CreateNetworksProvider()
6771
{
68-
return new CloudNetworksProvider(Bootstrapper.Settings.TestIdentity, Bootstrapper.Settings.DefaultRegion, null, null);
72+
var provider = new CloudNetworksProvider(Bootstrapper.Settings.TestIdentity, Bootstrapper.Settings.DefaultRegion, CreateIdentityProvider(), null);
73+
SetUserAgent(provider);
74+
return provider;
6975
}
7076

7177
public static IBlockStorageProvider CreateBlockStorageProvider()
7278
{
73-
return new CloudBlockStorageProvider(Bootstrapper.Settings.TestIdentity, Bootstrapper.Settings.DefaultRegion, null, null);
79+
var provider = new CloudBlockStorageProvider(Bootstrapper.Settings.TestIdentity, Bootstrapper.Settings.DefaultRegion, CreateIdentityProvider(), null);
80+
SetUserAgent(provider);
81+
return provider;
7482
}
7583

7684
public static IObjectStorageProvider CreateObjectStorageProvider()
7785
{
78-
return new CloudFilesProvider(Bootstrapper.Settings.TestIdentity, Bootstrapper.Settings.DefaultRegion, null, null);
86+
var provider = new CloudFilesProvider(Bootstrapper.Settings.TestIdentity, Bootstrapper.Settings.DefaultRegion, CreateIdentityProvider(), null);
87+
SetUserAgent(provider);
88+
return provider;
89+
}
90+
91+
private static void SetUserAgent<T>(ProviderBase<T> provider)
92+
where T : class
93+
{
94+
provider.ApplicationUserAgent = "CI-BOT";
7995
}
8096
}
8197

0 commit comments

Comments
 (0)