Skip to content

Commit a433820

Browse files
committed
Adding user-agent string for .NET remote HTTP requests
Addresses #5657 for .NET.
1 parent 63f65c6 commit a433820

File tree

2 files changed

+98
-1
lines changed

2 files changed

+98
-1
lines changed

dotnet/src/webdriver/Internal/ResourceUtilities.cs

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// <copyright file="ResourceUtilities.cs" company="WebDriver Committers">
1+
// <copyright file="ResourceUtilities.cs" company="WebDriver Committers">
22
// Licensed to the Software Freedom Conservancy (SFC) under one
33
// or more contributor license agreements. See the NOTICE file
44
// distributed with this work for additional information
@@ -16,10 +16,13 @@
1616
// limitations under the License.
1717
// </copyright>
1818

19+
using System;
1920
using System.Collections.Generic;
21+
using System.Diagnostics;
2022
using System.Globalization;
2123
using System.IO;
2224
using System.Reflection;
25+
using System.Runtime.InteropServices;
2326

2427
namespace OpenQA.Selenium.Internal
2528
{
@@ -28,6 +31,43 @@ namespace OpenQA.Selenium.Internal
2831
/// </summary>
2932
public static class ResourceUtilities
3033
{
34+
private static string assemblyVersion;
35+
private static string platformFamily;
36+
37+
/// <summary>
38+
/// Gets a string representing the version of the Selenium assembly.
39+
/// </summary>
40+
public static string AssemblyVersion
41+
{
42+
get
43+
{
44+
if (string.IsNullOrEmpty(assemblyVersion))
45+
{
46+
Assembly executingAssembly = Assembly.GetCallingAssembly();
47+
Version versionResource = executingAssembly.GetName().Version;
48+
assemblyVersion = string.Format(CultureInfo.InvariantCulture, "{0}.{1}.{2}", versionResource.Major, versionResource.Minor, versionResource.Revision);
49+
}
50+
51+
return assemblyVersion;
52+
}
53+
}
54+
55+
/// <summary>
56+
/// Gets a string representing the platform family on which the Selenium assembly is executing.
57+
/// </summary>
58+
public static string PlatformFamily
59+
{
60+
get
61+
{
62+
if (string.IsNullOrEmpty(platformFamily))
63+
{
64+
platformFamily = GetPlatformString();
65+
}
66+
67+
return platformFamily;
68+
}
69+
}
70+
3171
/// <summary>
3272
/// Gets a <see cref="Stream"/> that contains the resource to use.
3373
/// </summary>
@@ -89,5 +129,56 @@ public static bool IsValidResourceName(string resourceId)
89129
List<string> resourceNames = new List<string>(executingAssembly.GetManifestResourceNames());
90130
return resourceNames.Contains(resourceId);
91131
}
132+
133+
private static string GetPlatformString()
134+
{
135+
string platformName = "unknown";
136+
#if NETSTANDARD2_0 || NETCOREAPP2_0
137+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
138+
{
139+
platformName = "windows";
140+
}
141+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
142+
{
143+
platformName = "linux";
144+
}
145+
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
146+
{
147+
platformName = "mac";
148+
}
149+
#else
150+
// Unfortunately, detecting the currently running platform isn't as
151+
// straightforward as you might hope.
152+
// See: http://mono.wikia.com/wiki/Detecting_the_execution_platform
153+
// and https://msdn.microsoft.com/en-us/library/3a8hyw88(v=vs.110).aspx
154+
const int PlatformMonoUnixValue = 128;
155+
PlatformID platformId = Environment.OSVersion.Platform;
156+
if (platformId == PlatformID.Unix || platformId == PlatformID.MacOSX || (int)platformId == PlatformMonoUnixValue)
157+
{
158+
using (Process unameProcess = new Process())
159+
{
160+
unameProcess.StartInfo.FileName = "uname";
161+
unameProcess.StartInfo.UseShellExecute = false;
162+
unameProcess.StartInfo.RedirectStandardOutput = true;
163+
unameProcess.Start();
164+
unameProcess.WaitForExit(1000);
165+
string output = unameProcess.StandardOutput.ReadToEnd();
166+
if (output.ToLowerInvariant().StartsWith("darwin"))
167+
{
168+
platformName = "mac";
169+
}
170+
else
171+
{
172+
platformName = "linux";
173+
}
174+
}
175+
}
176+
else if (platformId == PlatformID.Win32NT || platformId == PlatformID.Win32S || platformId == PlatformID.Win32Windows || platformId == PlatformID.WinCE)
177+
{
178+
platformName = "windows";
179+
}
180+
#endif
181+
return platformName;
182+
}
92183
}
93184
}

dotnet/src/webdriver/Remote/HttpCommandExecutor.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
using System.IO;
2323
using System.Net;
2424
using System.Text;
25+
using OpenQA.Selenium.Internal;
2526

2627
namespace OpenQA.Selenium.Remote
2728
{
@@ -35,6 +36,7 @@ public class HttpCommandExecutor : ICommandExecutor
3536
private const string CharsetType = "charset=utf-8";
3637
private const string ContentTypeHeader = JsonMimeType + ";" + CharsetType;
3738
private const string RequestAcceptHeader = JsonMimeType + ", " + PngMimeType;
39+
private const string UserAgentHeaderTemplate = "selenium/{0} (.net {1})";
3840
private Uri remoteServerUri;
3941
private TimeSpan serverResponseTimeout;
4042
private bool enableKeepAlive;
@@ -84,6 +86,8 @@ public HttpCommandExecutor(Uri addressOfRemoteServer, TimeSpan timeout, bool ena
8486
{
8587
HttpWebRequest.DefaultMaximumErrorResponseLength = -1;
8688
}
89+
90+
8791
}
8892

8993
public event EventHandler<BeforeRemoteHttpRequestEventArgs> BeforeRemoteHttpRequest;
@@ -175,6 +179,8 @@ private HttpResponseInfo MakeHttpRequest(HttpRequestInfo requestInfo)
175179
request.PreAuthenticate = true;
176180
}
177181

182+
string userAgentString = string.Format(CultureInfo.InvariantCulture, UserAgentHeaderTemplate, ResourceUtilities.AssemblyVersion, ResourceUtilities.PlatformFamily);
183+
request.UserAgent = userAgentString;
178184
request.Method = requestInfo.HttpMethod;
179185
request.Timeout = (int)this.serverResponseTimeout.TotalMilliseconds;
180186
request.Accept = RequestAcceptHeader;

0 commit comments

Comments
 (0)