You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by va...@apache.org on 2022/12/05 22:03:40 UTC
[tinkerpop] branch 3.5-dev updated: Add User-Agent connection header to dotnet GLV User agent follows the form of [Application Name] [GLV Name].[Version] [Language Runtime Version] [OS].[Version] [CPU Architecture]
This is an automated email from the ASF dual-hosted git repository.
valentyn pushed a commit to branch 3.5-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/3.5-dev by this push:
new da7ab3a5cf Add User-Agent connection header to dotnet GLV User agent follows the form of [Application Name] [GLV Name].[Version] [Language Runtime Version] [OS].[Version] [CPU Architecture]
new 7e551b8d13 Merge pull request #1876 from Bit-Quill/cole/user-agent-dotnet
da7ab3a5cf is described below
commit da7ab3a5cfe21fb83447b352bed9085d775f4bf5
Author: Cole Greer <co...@bitquilltech.com>
AuthorDate: Fri Oct 14 12:07:14 2022 -0700
Add User-Agent connection header to dotnet GLV
User agent follows the form of [Application Name] [GLV Name].[Version] [Language Runtime Version] [OS].[Version] [CPU Architecture]
New feature in the dotnet driver to send a user agent header during the web socket handshake for new connections.
This behavior is enabled by default but can be disabled by setting ConnectionPoolSettings.EnableUserAgentOnConnect to false.
---
CHANGELOG.asciidoc | 1 +
docs/src/reference/gremlin-variants.asciidoc | 3 +++
.../Gremlin.Net/Driver/ConnectionPoolSettings.cs | 13 ++++++++++-
.../src/Gremlin.Net/Driver/GremlinClient.cs | 9 ++++++--
.../src/Gremlin.Net/Driver/WebSocketConnection.cs | 6 +++++
.../src/Gremlin.Net/Driver/WebSocketSettings.cs | 2 ++
gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs | 27 +++++++++++++++++++++-
7 files changed, 57 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 6583ec4f7b..dacacea2a1 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -36,6 +36,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
* Async operations in .NET can now be cancelled. This however does not cancel work that is already happening on the server.
* Bumped to `snakeyaml` 1.32 to fix security vulnerability.
* Added user agent to web socket handshake in java driver. Can be controlled by a new enableUserAgentOnConnect configuration. It is enabled by default.
+* Added user agent to web socket handshake in Gremlin.Net driver. Can be controlled by `EnableUserAgentOnConnect` in `ConnectionPoolSettings`. It is enabled by default.
* Added logging in .NET.
* Added `addDefaultXModule` to `GraphSONMapper` as a shortcut for including a version matched GraphSON extension module.
* Modified `GraphSONRecordReader` and `GraphSONRecordWriter` to include the GraphSON extension module by default.
diff --git a/docs/src/reference/gremlin-variants.asciidoc b/docs/src/reference/gremlin-variants.asciidoc
index e9e2744062..2517c39c59 100644
--- a/docs/src/reference/gremlin-variants.asciidoc
+++ b/docs/src/reference/gremlin-variants.asciidoc
@@ -1127,6 +1127,9 @@ on the `ConnectionPoolSettings` instance that can be passed to the `GremlinClien
|MaxInProcessPerConnection |The maximum number of in-flight requests that can occur on a connection. |32
|ReconnectionAttempts |The number of attempts to get an open connection from the pool to submit a request. |4
|ReconnectionBaseDelay |The base delay used for the exponential backoff for the reconnection attempts. |1 s
+|EnableUserAgentOnConnect |Enables sending a user agent to the server during connection requests.
+More details can be found in provider docs
+link:https://tinkerpop.apache.org/docs/x.y.z/dev/provider/#_graph_driver_provider_requirements[here].|true
|=========================================================
A `NoConnectionAvailableException` is thrown if all connections have reached the `MaxInProcessPerConnection` limit
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionPoolSettings.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionPoolSettings.cs
index 01965989df..bccd5d63b4 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionPoolSettings.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/ConnectionPoolSettings.cs
@@ -39,6 +39,7 @@ namespace Gremlin.Net.Driver
private const int DefaultMaxInProcessPerConnection = 32;
private const int DefaultReconnectionAttempts = 4;
private static readonly TimeSpan DefaultReconnectionBaseDelay = TimeSpan.FromSeconds(1);
+ internal const bool DefaultEnableUserAgentOnConnect = true;
/// <summary>
/// Gets or sets the size of the connection pool.
@@ -131,5 +132,15 @@ namespace Gremlin.Net.Driver
_reconnectionBaseDelay = value;
}
}
+
+ /// <summary>
+ /// Gets or sets whether a connection pool will send a user agent during web socket handshakes
+ /// </summary>
+ /// <remarks>
+ /// The default value is true. When enabled, user agents will only be sent during the web socket
+ /// handshake. User agent follows the form:
+ /// [Application Name] [GLV Name].[Version] [Language Runtime Version] [OS].[Version] [CPU Architecture]
+ /// </remarks>
+ public bool EnableUserAgentOnConnect { get; set; } = DefaultEnableUserAgentOnConnect;
}
-}
\ No newline at end of file
+}
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs
index d156c67d04..a688c53879 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/GremlinClient.cs
@@ -108,7 +108,11 @@ namespace Gremlin.Net.Driver
var connectionFactory =
new ConnectionFactory(gremlinServer, messageSerializer,
- new WebSocketSettings { WebSocketConfigurationCallback = webSocketConfiguration }, sessionId);
+ new WebSocketSettings
+ {
+ WebSocketConfigurationCallback = webSocketConfiguration,
+ EnableUserAgentOnConnect = connectionPoolSettings?.EnableUserAgentOnConnect ?? ConnectionPoolSettings.DefaultEnableUserAgentOnConnect
+ }, sessionId);
// make sure one connection in pool as session mode
if (!string.IsNullOrEmpty(sessionId))
@@ -171,7 +175,8 @@ namespace Gremlin.Net.Driver
messageSerializer ??= new GraphSON3MessageSerializer();
var webSocketSettings = new WebSocketSettings
{
- WebSocketConfigurationCallback = webSocketConfiguration
+ WebSocketConfigurationCallback = webSocketConfiguration,
+ EnableUserAgentOnConnect = connectionPoolSettings?.EnableUserAgentOnConnect ?? ConnectionPoolSettings.DefaultEnableUserAgentOnConnect
#if NET6_0_OR_GREATER
, UseCompression = !disableCompression
#endif
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketConnection.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketConnection.cs
index 5286409f3a..0a5bee90d0 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketConnection.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketConnection.cs
@@ -27,6 +27,7 @@ using System.IO;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;
+using Gremlin.Net.Process;
namespace Gremlin.Net.Driver
{
@@ -47,9 +48,14 @@ namespace Gremlin.Net.Driver
private const int ReceiveBufferSize = 1024;
private const WebSocketMessageType MessageType = WebSocketMessageType.Binary;
private readonly IClientWebSocket _client;
+ private const string userAgentHeaderName = "User-Agent";
public WebSocketConnection(IClientWebSocket client, WebSocketSettings settings)
{
+ if (settings.EnableUserAgentOnConnect)
+ {
+ client.Options.SetRequestHeader(userAgentHeaderName, Utils.UserAgent);
+ }
_client = client;
#if NET6_0_OR_GREATER
diff --git a/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketSettings.cs b/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketSettings.cs
index 5e7722a154..7cb794e6a8 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketSettings.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Driver/WebSocketSettings.cs
@@ -41,6 +41,8 @@ namespace Gremlin.Net.Driver
/// </summary>
public Action<ClientWebSocketOptions> WebSocketConfigurationCallback { get; set; }
+ public bool EnableUserAgentOnConnect { get; set; }
+
#if NET6_0_OR_GREATER
/// <summary>
/// Gets or sets whether compressions will be used. The default is true. (Only available since .NET 6.)
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs
index 27d5de114a..ed96830222 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Utils.cs
@@ -22,8 +22,10 @@
#endregion
using System;
+using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
+using static System.Runtime.InteropServices.RuntimeInformation;
namespace Gremlin.Net.Process
{
@@ -32,6 +34,9 @@ namespace Gremlin.Net.Process
/// </summary>
internal static class Utils
{
+ public static string UserAgent => _userAgent ??= GenerateUserAgent();
+ private static string _userAgent;
+
/// <summary>
/// Waits the completion of the provided Task.
/// When an AggregateException is thrown, the inner exception is thrown.
@@ -63,5 +68,25 @@ namespace Gremlin.Net.Process
t.Exception?.Handle(_ => true);
}, TaskContinuationOptions.ExecuteSynchronously);
}
+
+ /// <summary>
+ /// Returns a user agent for connection request headers.
+ ///
+ /// Format:
+ /// "[Application Name] [GLV Name].[Version] [Language Runtime Version] [OS].[Version] [CPU Architecture]"
+ /// </summary>
+ private static string GenerateUserAgent()
+ {
+ var applicationName = Assembly.GetExecutingAssembly().GetName().Name?
+ .Replace(' ', '_') ?? "NotAvailable";
+ var driverVersion = AssemblyName.GetAssemblyName("Gremlin.Net.dll").Version?.ToString()
+ .Replace(' ', '_') ?? "NotAvailable";
+ var languageVersion = Environment.Version.ToString().Replace(' ', '_');
+ var osName = Environment.OSVersion.Platform.ToString().Replace(' ', '_');
+ var osVersion = Environment.OSVersion.Version.ToString().Replace(' ', '_');
+ var cpuArchitecture = OSArchitecture.ToString().Replace(' ', '_');
+
+ return $"{applicationName} gremlin-dotnet.{driverVersion} {languageVersion} {osName}.{osVersion} {cpuArchitecture}";
+ }
}
-}
\ No newline at end of file
+}