diff --git a/src/Elastic.Transport.VirtualizedCluster/Components/ExposingPipelineFactory.cs b/src/Elastic.Transport.VirtualizedCluster/Components/ExposingPipelineFactory.cs
index 4fd0586..b2601fe 100644
--- a/src/Elastic.Transport.VirtualizedCluster/Components/ExposingPipelineFactory.cs
+++ b/src/Elastic.Transport.VirtualizedCluster/Components/ExposingPipelineFactory.cs
@@ -8,25 +8,23 @@ namespace Elastic.Transport.VirtualizedCluster.Components;
///
/// An implementation that exposes all the components so that can reference them directly.
///
-public sealed class ExposingPipelineFactory : RequestPipelineFactory where TConfiguration : class, ITransportConfiguration
+public sealed class ExposingPipelineFactory : RequestPipelineFactory
+ where TConfiguration : class, ITransportConfiguration
{
public ExposingPipelineFactory(TConfiguration configuration, DateTimeProvider dateTimeProvider)
{
DateTimeProvider = dateTimeProvider;
- MemoryStreamFactory = TransportConfiguration.DefaultMemoryStreamFactory;
Configuration = configuration;
- Pipeline = Create(Configuration, DateTimeProvider, MemoryStreamFactory, null);
- RequestHandler = new DistributedTransport(Configuration, this, DateTimeProvider, MemoryStreamFactory);
+ Pipeline = Create(new RequestData(Configuration, null, null), DateTimeProvider);
+ RequestHandler = new DistributedTransport(Configuration, this, DateTimeProvider);
}
// ReSharper disable once MemberCanBePrivate.Global
public RequestPipeline Pipeline { get; }
private DateTimeProvider DateTimeProvider { get; }
- private MemoryStreamFactory MemoryStreamFactory { get; }
private TConfiguration Configuration { get; }
public ITransport RequestHandler { get; }
- public override RequestPipeline Create(TConfiguration configurationValues, DateTimeProvider dateTimeProvider,
- MemoryStreamFactory memoryStreamFactory, IRequestConfiguration? requestConfiguration) =>
- new DefaultRequestPipeline(Configuration, DateTimeProvider, MemoryStreamFactory, requestConfiguration);
+ public override RequestPipeline Create(RequestData requestData, DateTimeProvider dateTimeProvider) =>
+ new DefaultRequestPipeline(requestData, DateTimeProvider);
}
diff --git a/src/Elastic.Transport.VirtualizedCluster/Components/SealedVirtualCluster.cs b/src/Elastic.Transport.VirtualizedCluster/Components/SealedVirtualCluster.cs
index f479f92..f2b1c1b 100644
--- a/src/Elastic.Transport.VirtualizedCluster/Components/SealedVirtualCluster.cs
+++ b/src/Elastic.Transport.VirtualizedCluster/Components/SealedVirtualCluster.cs
@@ -10,7 +10,7 @@ namespace Elastic.Transport.VirtualizedCluster.Components;
///
/// A continuation of 's builder methods that creates
-/// an instance of for the cluster after which the components such as
+/// an instance of for the cluster after which the components such as
/// and can no longer be updated.
///
public sealed class SealedVirtualCluster
@@ -28,23 +28,23 @@ internal SealedVirtualCluster(VirtualCluster cluster, NodePool pool, TestableDat
_productRegistration = productRegistration;
}
- private TransportConfiguration CreateSettings() =>
+ private TransportConfigurationDescriptor CreateSettings() =>
new(_nodePool, _requestInvoker, serializer: null, _productRegistration.ProductRegistration);
- /// Create the cluster using all defaults on
+ /// Create the cluster using all defaults on
public VirtualizedCluster AllDefaults() =>
new(_dateTimeProvider, CreateSettings());
/// Create the cluster using to provide configuration changes
/// Provide custom configuration options
- public VirtualizedCluster Settings(Func selector) =>
+ public VirtualizedCluster Settings(Func selector) =>
new(_dateTimeProvider, selector(CreateSettings()));
///
/// Allows you to create an instance of ` using the DSL provided by
///
/// Provide custom configuration options
- public VirtualClusterRequestInvoker VirtualClusterConnection(Func selector = null) =>
+ public VirtualClusterRequestInvoker VirtualClusterConnection(Func selector = null) =>
new VirtualizedCluster(_dateTimeProvider, selector == null ? CreateSettings() : selector(CreateSettings()))
.Connection;
}
diff --git a/src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs b/src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs
index 6ab83c4..20ddf3f 100644
--- a/src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs
+++ b/src/Elastic.Transport.VirtualizedCluster/Components/VirtualizedCluster.cs
@@ -13,7 +13,7 @@ public class VirtualizedCluster
{
private readonly ExposingPipelineFactory _exposingRequestPipeline;
private readonly TestableDateTimeProvider _dateTimeProvider;
- private readonly TransportConfiguration _settings;
+ private readonly TransportConfigurationDescriptor _settings;
private Func, Func, Task> _asyncCall;
private Func, Func, TransportResponse> _syncCall;
@@ -22,7 +22,7 @@ private class VirtualResponse : TransportResponse;
private static readonly EndpointPath RootPath = new(HttpMethod.GET, "/");
- internal VirtualizedCluster(TestableDateTimeProvider dateTimeProvider, TransportConfiguration settings)
+ internal VirtualizedCluster(TestableDateTimeProvider dateTimeProvider, TransportConfigurationDescriptor settings)
{
_dateTimeProvider = dateTimeProvider;
_settings = settings;
diff --git a/src/Elastic.Transport/Components/Endpoint.cs b/src/Elastic.Transport/Components/Endpoint.cs
new file mode 100644
index 0000000..699dc0e
--- /dev/null
+++ b/src/Elastic.Transport/Components/Endpoint.cs
@@ -0,0 +1,66 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using System;
+
+namespace Elastic.Transport;
+
+///
+/// Represents the path of an endpoint in a transport request, including the HTTP method
+/// and the path and query information.
+///
+///
+/// This struct is used to store information about the HTTP method and the path and query of an endpoint,
+/// which are essential components when constructing a request URI.
+///
+public readonly record struct EndpointPath(HttpMethod Method, string PathAndQuery);
+
+///
+/// Represents an endpoint in a transport request, encapsulating the HTTP method, path and query,
+/// and the node to which the request is being sent.
+///
+///
+/// This class is used to construct the URI for the request based on the node's URI and the path and query.
+/// An empty endpoint can be created using the method as a default or placeholder instance.
+///
+public record Endpoint(in EndpointPath Path, Node Node)
+{
+ /// Represents an empty endpoint used as a default or placeholder instance of .
+ public static Endpoint Empty(in EndpointPath path) => new(path, EmptyNode);
+
+ private static readonly Node EmptyNode = new(new Uri("http://empty.example"));
+
+ /// Indicates whether the endpoint is an empty placeholder instance.
+ public bool IsEmpty => Node == EmptyNode;
+
+ /// The for the request.
+ public Uri Uri { get; private init; } = new(Node.Uri, Path.PathAndQuery);
+
+ /// The HTTP method used for the request (e.g., GET, POST, PUT, DELETE, HEAD).
+ public HttpMethod Method => Path.Method;
+
+ /// Gets the path and query of the endpoint.
+ public string PathAndQuery => Path.PathAndQuery;
+
+ private readonly Node _node = Node;
+
+ ///
+ /// Represents a node within the transport layer of the Elastic search client.
+ /// This object encapsulates the characteristics of a node, allowing for comparisons and operations
+ /// within the broader search infrastructure.
+ ///
+ public Node Node
+ {
+ get => _node;
+ init
+ {
+ _node = value;
+ Uri = new(Node.Uri, Path.PathAndQuery);
+ }
+ }
+
+ ///
+ public override string ToString() => $"{Path.Method.GetStringValue()} {Uri}";
+
+}
diff --git a/src/Elastic.Transport/Components/Pipeline/DefaultRequestPipeline.cs b/src/Elastic.Transport/Components/Pipeline/DefaultRequestPipeline.cs
index af31cad..19b7d64 100644
--- a/src/Elastic.Transport/Components/Pipeline/DefaultRequestPipeline.cs
+++ b/src/Elastic.Transport/Components/Pipeline/DefaultRequestPipeline.cs
@@ -16,43 +16,40 @@
namespace Elastic.Transport;
///
-public class DefaultRequestPipeline : RequestPipeline
- where TConfiguration : class, ITransportConfiguration
+public class DefaultRequestPipeline : RequestPipeline
{
private readonly IRequestInvoker _requestInvoker;
private readonly NodePool _nodePool;
+ private readonly RequestData _requestData;
private readonly DateTimeProvider _dateTimeProvider;
private readonly MemoryStreamFactory _memoryStreamFactory;
private readonly Func _nodePredicate;
private readonly ProductRegistration _productRegistration;
- private readonly TConfiguration _settings;
private readonly ResponseBuilder _responseBuilder;
private RequestConfiguration? _pingAndSniffRequestConfiguration;
- private List _auditTrail = null;
+ private List? _auditTrail;
+ private readonly ITransportConfiguration _settings;
///
- internal DefaultRequestPipeline(
- TConfiguration configurationValues,
- DateTimeProvider dateTimeProvider,
- MemoryStreamFactory memoryStreamFactory,
- IRequestConfiguration? requestConfiguration
- )
+ internal DefaultRequestPipeline(RequestData requestData, DateTimeProvider dateTimeProvider)
{
- _settings = configurationValues;
- _nodePool = _settings.NodePool;
- _requestInvoker = _settings.Connection;
+ _requestData = requestData;
+ _settings = requestData.ConnectionSettings;
+
+ _nodePool = requestData.ConnectionSettings.NodePool;
+ _requestInvoker = requestData.ConnectionSettings.Connection;
_dateTimeProvider = dateTimeProvider;
- _memoryStreamFactory = memoryStreamFactory;
- _productRegistration = configurationValues.ProductRegistration;
+ _memoryStreamFactory = requestData.MemoryStreamFactory;
+ _productRegistration = requestData.ConnectionSettings.ProductRegistration;
_responseBuilder = _productRegistration.ResponseBuilder;
- _nodePredicate = _settings.NodePredicate ?? _productRegistration.NodePredicate;
- RequestConfig = requestConfiguration;
+ _nodePredicate = requestData.ConnectionSettings.NodePredicate ?? _productRegistration.NodePredicate;
+
StartedOn = dateTimeProvider.Now();
}
///
- public override IEnumerable AuditTrail => _auditTrail ?? (IEnumerable)Array.Empty();
+ public override IEnumerable AuditTrail => _auditTrail;
private RequestConfiguration PingAndSniffRequestConfiguration
{
@@ -66,9 +63,9 @@ private RequestConfiguration PingAndSniffRequestConfiguration
{
PingTimeout = PingTimeout,
RequestTimeout = PingTimeout,
- Authentication = RequestConfig?.Authentication ?? _settings.Authentication,
- EnableHttpPipelining = RequestConfig?.HttpPipeliningEnabled ?? _settings.HttpPipeliningEnabled,
- ForceNode = RequestConfig?.ForceNode
+ Authentication = _requestData.AuthenticationHeader,
+ EnableHttpPipelining = _requestData.HttpPipeliningEnabled,
+ ForceNode = _requestData.ForceNode
};
return _pingAndSniffRequestConfiguration;
@@ -99,10 +96,7 @@ public override bool IsTakingTooLong
}
}
- public override int MaxRetries =>
- RequestConfig?.ForceNode != null
- ? 0
- : Math.Min(RequestConfig?.MaxRetries ?? _settings.MaxRetries.GetValueOrDefault(int.MaxValue), _nodePool.MaxRetries);
+ public override int MaxRetries => _requestData.MaxRetries;
public bool Refresh { get; private set; }
@@ -140,18 +134,13 @@ public override bool StaleClusterState
public override DateTimeOffset StartedOn { get; }
- private TimeSpan PingTimeout =>
- RequestConfig?.PingTimeout
- ?? _settings.PingTimeout
- ?? (_nodePool.UsingSsl ? RequestConfiguration.DefaultPingTimeoutOnSsl : RequestConfiguration.DefaultPingTimeout);
+ private TimeSpan PingTimeout => _requestData.PingTimeout;
- private IRequestConfiguration RequestConfig { get; }
+ private bool RequestDisabledSniff => _requestData.DisableSniff;
- private bool RequestDisabledSniff => RequestConfig != null && (RequestConfig.DisableSniff ?? false);
+ private TimeSpan RequestTimeout => _requestData.RequestTimeout;
- private TimeSpan RequestTimeout => RequestConfig?.RequestTimeout ?? _settings.RequestTimeout ?? RequestConfiguration.DefaultRequestTimeout;
-
- public override void AuditCancellationRequested() => Audit(CancellationRequested).Dispose();
+ public override void AuditCancellationRequested() => Audit(CancellationRequested)?.Dispose();
public override void BadResponse(ref TResponse response, ApiCallDetails callDetails, Endpoint endpoint, RequestData data, PostData? postData, TransportException exception)
{
@@ -362,9 +351,9 @@ public override bool TryGetSingleNode(out Node node)
public override IEnumerable NextNode()
{
- if (RequestConfig?.ForceNode != null)
+ if (_requestData.ForceNode != null)
{
- yield return new Node(RequestConfig.ForceNode);
+ yield return new Node(_requestData.ForceNode);
yield break;
}
@@ -416,15 +405,12 @@ public async ValueTask PingCoreAsync(bool isAsync, Node node, CancellationToken
TransportResponse response;
- //TODO remove
- var requestData = new RequestData(_settings, null, null, _memoryStreamFactory);
-
try
{
if (isAsync)
- response = await _productRegistration.PingAsync(_requestInvoker, pingEndpoint, requestData, cancellationToken).ConfigureAwait(false);
+ response = await _productRegistration.PingAsync(_requestInvoker, pingEndpoint, _requestData, cancellationToken).ConfigureAwait(false);
else
- response = _productRegistration.Ping(_requestInvoker, pingEndpoint, requestData);
+ response = _productRegistration.Ping(_requestInvoker, pingEndpoint, _requestData);
ThrowBadAuthPipelineExceptionWhenNeeded(response.ApiCallDetails);
@@ -462,7 +448,7 @@ public async ValueTask SniffCoreAsync(bool isAsync, CancellationToken cancellati
{
var sniffEndpoint = _productRegistration.CreateSniffEndpoint(node, PingAndSniffRequestConfiguration, _settings);
//TODO remove
- var requestData = new RequestData(_settings, null, null, _memoryStreamFactory);
+ var requestData = new RequestData(_settings, null, null);
using var audit = Audit(SniffSuccess, node);
@@ -554,9 +540,7 @@ public override void ThrowNoNodesAttempted(Endpoint endpoint, List
- (RequestConfig?.DisablePings).GetValueOrDefault(false)
- || (_settings.DisablePings ?? false) || !_nodePool.SupportsPinging || !node.IsResurrected;
+ private bool PingDisabled(Node node) => _requestData.DisablePings || !node.IsResurrected;
private Auditable? Audit(AuditEvent type, Node node = null) =>
!_settings.DisableAuditTrail ?? true ? new(type, ref _auditTrail, _dateTimeProvider, node) : null;
diff --git a/src/Elastic.Transport/Components/Pipeline/DefaultResponseBuilder.cs b/src/Elastic.Transport/Components/Pipeline/DefaultResponseBuilder.cs
index 0bb90c3..88c8225 100644
--- a/src/Elastic.Transport/Components/Pipeline/DefaultResponseBuilder.cs
+++ b/src/Elastic.Transport/Components/Pipeline/DefaultResponseBuilder.cs
@@ -228,7 +228,7 @@ private async ValueTask SetBodyCoreAsync(bool isAsync,
return response;
}
- if (!requestData.ValidateResponseContentType(mimeType))
+ if (!ValidateResponseContentType(requestData.Accept, mimeType))
{
ConditionalDisposal(responseStream, ownsStream, response);
return default;
diff --git a/src/Elastic.Transport/Components/Pipeline/PipelineException.cs b/src/Elastic.Transport/Components/Pipeline/PipelineException.cs
index ba035a3..37f92e2 100644
--- a/src/Elastic.Transport/Components/Pipeline/PipelineException.cs
+++ b/src/Elastic.Transport/Components/Pipeline/PipelineException.cs
@@ -7,7 +7,7 @@
namespace Elastic.Transport;
///
-/// A pipeline exception is throw when ever a known failing exit point is reached in
+/// A pipeline exception is throw when ever a known failing exit point is reached in
/// See for known exits points
///
public class PipelineException : Exception
diff --git a/src/Elastic.Transport/Components/Pipeline/PipelineFailure.cs b/src/Elastic.Transport/Components/Pipeline/PipelineFailure.cs
index 585114b..4312188 100644
--- a/src/Elastic.Transport/Components/Pipeline/PipelineFailure.cs
+++ b/src/Elastic.Transport/Components/Pipeline/PipelineFailure.cs
@@ -7,7 +7,7 @@
namespace Elastic.Transport;
///
-/// A failure in 's workflow that caused it to end prematurely.
+/// A failure in 's workflow that caused it to end prematurely.
///
public enum PipelineFailure
{
@@ -43,7 +43,7 @@ public enum PipelineFailure
MaxRetriesReached,
///
- /// An exception occurred during that could not be handled
+ /// An exception occurred during that could not be handled
///
Unexpected,
diff --git a/src/Elastic.Transport/Components/Pipeline/RequestData.cs b/src/Elastic.Transport/Components/Pipeline/RequestData.cs
index 778ab7b..6cb1b50 100644
--- a/src/Elastic.Transport/Components/Pipeline/RequestData.cs
+++ b/src/Elastic.Transport/Components/Pipeline/RequestData.cs
@@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
+using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Elastic.Transport.Diagnostics;
using Elastic.Transport.Diagnostics.Auditing;
@@ -12,66 +13,6 @@
namespace Elastic.Transport;
-///
-/// Represents the path of an endpoint in a transport request, including the HTTP method
-/// and the path and query information.
-///
-///
-/// This struct is used to store information about the HTTP method and the path and query of an endpoint,
-/// which are essential components when constructing a request URI.
-///
-public readonly record struct EndpointPath(HttpMethod Method, string PathAndQuery);
-
-
-///
-/// Represents an endpoint in a transport request, encapsulating the HTTP method, path and query,
-/// and the node to which the request is being sent.
-///
-///
-/// This class is used to construct the URI for the request based on the node's URI and the path and query.
-/// An empty endpoint can be created using the method as a default or placeholder instance.
-///
-public record Endpoint(in EndpointPath Path, Node Node)
-{
- /// Represents an empty endpoint used as a default or placeholder instance of .
- public static Endpoint Empty(in EndpointPath path) => new(path, EmptyNode);
-
- private static readonly Node EmptyNode = new(new Uri("http://empty.example"));
-
- /// Indicates whether the endpoint is an empty placeholder instance.
- public bool IsEmpty => Node == EmptyNode;
-
- /// The for the request.
- public Uri Uri { get; private init; } = new(Node.Uri, Path.PathAndQuery);
-
- /// The HTTP method used for the request (e.g., GET, POST, PUT, DELETE, HEAD).
- public HttpMethod Method => Path.Method;
-
- /// Gets the path and query of the endpoint.
- public string PathAndQuery => Path.PathAndQuery;
-
- private readonly Node _node = Node;
-
- ///
- /// Represents a node within the transport layer of the Elastic search client.
- /// This object encapsulates the characteristics of a node, allowing for comparisons and operations
- /// within the broader search infrastructure.
- ///
- public Node Node
- {
- get => _node;
- init
- {
- _node = value;
- Uri = new(Node.Uri, Path.PathAndQuery);
- }
- }
-
- ///
- public override string ToString() => $"{Path.Method.GetStringValue()} {Uri}";
-
-}
-
///
/// Where and how should connect to.
///
@@ -79,26 +20,24 @@ public Node Node
/// and .
///
///
-public sealed class RequestData
+public sealed record RequestData
{
-//TODO add xmldocs and clean up this class
-#pragma warning disable 1591
+ private const string OpaqueIdHeader = "X-Opaque-Id";
+
+ /// The default MIME type used for request and response payloads.
public const string DefaultMimeType = "application/json";
- public const string OpaqueIdHeader = "X-Opaque-Id";
+
+ /// The security header used to run requests as a different user.
public const string RunAsSecurityHeader = "es-security-runas-user";
- public RequestData(
- ITransportConfiguration global,
- IRequestConfiguration? local,
- CustomResponseBuilder? customResponseBuilder,
- MemoryStreamFactory memoryStreamFactory
- )
+ ///
+ public RequestData(ITransportConfiguration global, IRequestConfiguration? local = null, CustomResponseBuilder? customResponseBuilder = null)
{
CustomResponseBuilder = customResponseBuilder;
ConnectionSettings = global;
- MemoryStreamFactory = memoryStreamFactory;
+ MemoryStreamFactory = global.MemoryStreamFactory;
- SkipDeserializationForStatusCodes = global.SkipDeserializationForStatusCodes;
+ SkipDeserializationForStatusCodes = global.SkipDeserializationForStatusCodes ?? [];
DnsRefreshTimeout = global.DnsRefreshTimeout;
MetaHeaderProvider = global.MetaHeaderProvider;
ProxyAddress = global.ProxyAddress;
@@ -113,7 +52,13 @@ MemoryStreamFactory memoryStreamFactory
DisableDirectStreaming = local?.DisableDirectStreaming ?? global.DisableDirectStreaming ?? false;
- Pipelined = local?.HttpPipeliningEnabled ?? global.HttpPipeliningEnabled ?? true;
+ ForceNode = global.ForceNode ?? local?.ForceNode;
+ MaxRetries = ForceNode != null ? 0
+ : Math.Min(global.MaxRetries.GetValueOrDefault(int.MaxValue), global.NodePool.MaxRetries);
+ DisableSniff = global.DisableSniff ?? local?.DisableSniff ?? false;
+ DisablePings = global.DisablePings ?? !global.NodePool.SupportsPinging;
+
+ HttpPipeliningEnabled = local?.HttpPipeliningEnabled ?? global.HttpPipeliningEnabled ?? true;
HttpCompression = global.EnableHttpCompression ?? local?.EnableHttpCompression ?? true;
ContentType = local?.ContentType ?? global.Accept ?? DefaultMimeType;
Accept = local?.Accept ?? global.Accept ?? DefaultMimeType;
@@ -124,8 +69,8 @@ MemoryStreamFactory memoryStreamFactory
AllowedStatusCodes = local?.AllowedStatusCodes ?? EmptyReadOnly.Collection;
ClientCertificates = local?.ClientCertificates ?? global.ClientCertificates;
TransferEncodingChunked = local?.TransferEncodingChunked ?? global.TransferEncodingChunked ?? false;
- TcpStats = local?.EnableTcpStats ?? global.EnableTcpStats ?? true;
- ThreadPoolStats = local?.EnableThreadPoolStats ?? global.EnableThreadPoolStats ?? true;
+ EnableTcpStats = local?.EnableTcpStats ?? global.EnableTcpStats ?? true;
+ EnableThreadPoolStats = local?.EnableThreadPoolStats ?? global.EnableThreadPoolStats ?? true;
ParseAllHeaders = local?.ParseAllHeaders ?? global.ParseAllHeaders ?? false;
ResponseHeadersToParse = local is not null
? new HeadersList(local.ResponseHeadersToParse, global.ResponseHeadersToParse)
@@ -153,65 +98,81 @@ MemoryStreamFactory memoryStreamFactory
}
+ ///
+ public MemoryStreamFactory MemoryStreamFactory { get; }
+ ///
+ public MetaHeaderProvider? MetaHeaderProvider { get; }
+ ///
+ public bool DisableAutomaticProxyDetection { get; }
+ ///
+ public int KeepAliveInterval { get; }
+ ///
+ public int KeepAliveTime { get; }
+ ///
+ public string? ProxyAddress { get; }
+ ///
+ public string? ProxyPassword { get; }
+ ///
+ public string? ProxyUsername { get; }
+ ///
+ public IReadOnlyCollection SkipDeserializationForStatusCodes { get; }
+ ///
+ public UserAgent UserAgent { get; }
+ ///
+ public TimeSpan DnsRefreshTimeout { get; }
+
+
+ ///
+ public IReadOnlyDictionary RequestMetaData { get; }
+
+ ///
public string Accept { get; }
+ ///
public IReadOnlyCollection AllowedStatusCodes { get; }
+ ///
public AuthorizationHeader? AuthenticationHeader { get; }
+ ///
public X509CertificateCollection? ClientCertificates { get; }
+ ///
public ITransportConfiguration ConnectionSettings { get; }
+ ///
public CustomResponseBuilder? CustomResponseBuilder { get; }
+ ///
public HeadersList? ResponseHeadersToParse { get; }
- public NameValueCollection? Headers { get; }
+ ///
+ public NameValueCollection Headers { get; }
+ ///
public bool DisableDirectStreaming { get; }
+ ///
public bool ParseAllHeaders { get; }
- public bool DisableAutomaticProxyDetection { get; }
+ ///
public bool HttpCompression { get; }
- public int KeepAliveInterval { get; }
- public int KeepAliveTime { get; }
- public MemoryStreamFactory MemoryStreamFactory { get; }
-
+ ///
+ public Uri? ForceNode { get; }
+ ///
public TimeSpan PingTimeout { get; }
- public bool Pipelined { get; }
- public string ProxyAddress { get; }
- public string ProxyPassword { get; }
- public string ProxyUsername { get; }
+ ///
+ public bool HttpPipeliningEnabled { get; }
+ ///
public string ContentType { get; }
+ ///
public TimeSpan RequestTimeout { get; }
+ ///
public string? RunAs { get; }
- public IReadOnlyCollection SkipDeserializationForStatusCodes { get; }
+ ///
public bool ThrowExceptions { get; }
- public UserAgent UserAgent { get; }
+ ///
public bool TransferEncodingChunked { get; }
- public bool TcpStats { get; }
- public bool ThreadPoolStats { get; }
-
- public TimeSpan DnsRefreshTimeout { get; }
-
- public MetaHeaderProvider? MetaHeaderProvider { get; }
-
- public IReadOnlyDictionary RequestMetaData { get; }
-
- //internal OpenTelemetryData OpenTelemetryData { get; }
-
- internal bool ValidateResponseContentType(string responseMimeType)
- {
- if (string.IsNullOrEmpty(responseMimeType)) return false;
-
- if (Accept == responseMimeType)
- return true;
-
- // TODO - Performance: Review options to avoid the replace here and compare more efficiently.
- var trimmedAccept = Accept.Replace(" ", "");
- var trimmedResponseMimeType = responseMimeType.Replace(" ", "");
-
- return trimmedResponseMimeType.Equals(trimmedAccept, StringComparison.OrdinalIgnoreCase)
- || trimmedResponseMimeType.StartsWith(trimmedAccept, StringComparison.OrdinalIgnoreCase)
-
- // ES specific fallback required because:
- // - 404 responses from ES8 don't include the vendored header
- // - ES8 EQL responses don't include vendored type
-
- || trimmedAccept.Contains("application/vnd.elasticsearch+json") && trimmedResponseMimeType.StartsWith(DefaultMimeType, StringComparison.OrdinalIgnoreCase);
- }
+ ///
+ public bool EnableTcpStats { get; }
+ ///
+ public bool EnableThreadPoolStats { get; }
+
+ ///
+ public int MaxRetries { get; }
+ ///
+ public bool DisableSniff { get; }
+ ///
+ public bool DisablePings { get; }
-#pragma warning restore 1591
}
diff --git a/src/Elastic.Transport/Components/Pipeline/RequestPipeline.cs b/src/Elastic.Transport/Components/Pipeline/RequestPipeline.cs
index 79dc658..99343b3 100644
--- a/src/Elastic.Transport/Components/Pipeline/RequestPipeline.cs
+++ b/src/Elastic.Transport/Components/Pipeline/RequestPipeline.cs
@@ -15,7 +15,7 @@ namespace Elastic.Transport;
///
public abstract class RequestPipeline : IDisposable
{
- private bool _disposed = false;
+ private bool _disposed;
internal RequestPipeline() { }
diff --git a/src/Elastic.Transport/Components/Pipeline/ResponseBuilder.cs b/src/Elastic.Transport/Components/Pipeline/ResponseBuilder.cs
index 95f18c3..643089b 100644
--- a/src/Elastic.Transport/Components/Pipeline/ResponseBuilder.cs
+++ b/src/Elastic.Transport/Components/Pipeline/ResponseBuilder.cs
@@ -83,7 +83,7 @@ long contentLength
// We don't validate the content-type (MIME type) for HEAD requests or responses that have no content (204 status code).
// Elastic Cloud responses to HEAD requests strip the content-type header so we want to avoid validation in that case.
- var hasExpectedContentType = !MayHaveBody(statusCode, endpoint.Method, contentLength) || requestData.ValidateResponseContentType(mimeType);
+ var hasExpectedContentType = !MayHaveBody(statusCode, endpoint.Method, contentLength) || ValidateResponseContentType(requestData.Accept, mimeType);
var details = new ApiCallDetails
{
@@ -114,4 +114,26 @@ long contentLength
protected static bool MayHaveBody(int? statusCode, HttpMethod httpMethod, long contentLength) =>
contentLength != 0 && (!statusCode.HasValue || statusCode.Value != 204 && httpMethod != HttpMethod.HEAD);
+ internal static bool ValidateResponseContentType(string accept, string responseMimeType)
+ {
+ if (string.IsNullOrEmpty(responseMimeType)) return false;
+
+ if (accept == responseMimeType)
+ return true;
+
+ // TODO - Performance: Review options to avoid the replace here and compare more efficiently.
+ var trimmedAccept = accept.Replace(" ", "");
+ var trimmedResponseMimeType = responseMimeType.Replace(" ", "");
+
+ return trimmedResponseMimeType.Equals(trimmedAccept, StringComparison.OrdinalIgnoreCase)
+ || trimmedResponseMimeType.StartsWith(trimmedAccept, StringComparison.OrdinalIgnoreCase)
+
+ // ES specific fallback required because:
+ // - 404 responses from ES8 don't include the vendored header
+ // - ES8 EQL responses don't include vendored type
+
+ || trimmedAccept.Contains("application/vnd.elasticsearch+json")
+ && trimmedResponseMimeType.StartsWith(RequestData.DefaultMimeType, StringComparison.OrdinalIgnoreCase);
+ }
+
}
diff --git a/src/Elastic.Transport/Components/Providers/DefaultRequestPipelineFactory.cs b/src/Elastic.Transport/Components/Providers/DefaultRequestPipelineFactory.cs
index 82779f2..0d137b3 100644
--- a/src/Elastic.Transport/Components/Providers/DefaultRequestPipelineFactory.cs
+++ b/src/Elastic.Transport/Components/Providers/DefaultRequestPipelineFactory.cs
@@ -5,15 +5,13 @@
namespace Elastic.Transport;
///
-/// The default implementation for that returns
+/// The default implementation for that returns
///
-internal sealed class DefaultRequestPipelineFactory : RequestPipelineFactory
- where TConfiguration : class, ITransportConfiguration
+internal sealed class DefaultRequestPipelineFactory : RequestPipelineFactory
{
///
- /// returns instances of
+ /// returns instances of
///
- public override RequestPipeline Create(TConfiguration configurationValues, DateTimeProvider dateTimeProvider,
- MemoryStreamFactory memoryStreamFactory, IRequestConfiguration? requestConfiguration) =>
- new DefaultRequestPipeline(configurationValues, dateTimeProvider, memoryStreamFactory, requestConfiguration);
+ public override RequestPipeline Create(RequestData requestData, DateTimeProvider dateTimeProvider) =>
+ new DefaultRequestPipeline(requestData, dateTimeProvider);
}
diff --git a/src/Elastic.Transport/Components/Providers/RequestPipelineFactory.cs b/src/Elastic.Transport/Components/Providers/RequestPipelineFactory.cs
index 25c8823..ff4ef38 100644
--- a/src/Elastic.Transport/Components/Providers/RequestPipelineFactory.cs
+++ b/src/Elastic.Transport/Components/Providers/RequestPipelineFactory.cs
@@ -5,12 +5,10 @@
namespace Elastic.Transport;
/// A factory that creates instances of , this factory exists so that transport can be tested.
-public abstract class RequestPipelineFactory
- where TConfiguration : class, ITransportConfiguration
+public abstract class RequestPipelineFactory
{
internal RequestPipelineFactory() { }
/// Create an instance of
- public abstract RequestPipeline Create(TConfiguration configuration, DateTimeProvider dateTimeProvider,
- MemoryStreamFactory memoryStreamFactory, IRequestConfiguration? requestParameters);
+ public abstract RequestPipeline Create(RequestData requestData, DateTimeProvider dateTimeProvider);
}
diff --git a/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs b/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs
index 00031d8..5593e1a 100644
--- a/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs
+++ b/src/Elastic.Transport/Components/TransportClient/HttpRequestInvoker.cs
@@ -26,8 +26,8 @@ namespace Elastic.Transport;
public class HttpRequestInvoker : IRequestInvoker
{
private static readonly string MissingConnectionLimitMethodError =
- $"Your target platform does not support {nameof(TransportConfiguration.ConnectionLimit)}"
- + $" please set {nameof(TransportConfiguration.ConnectionLimit)} to -1 on your configuration."
+ $"Your target platform does not support {nameof(TransportConfigurationDescriptor.ConnectionLimit)}"
+ + $" please set {nameof(TransportConfigurationDescriptor.ConnectionLimit)} to -1 on your configuration."
+ $" this will cause the {nameof(HttpClientHandler.MaxConnectionsPerServer)} not to be set on {nameof(HttpClientHandler)}";
private string _expectedCertificateFingerprint;
@@ -96,10 +96,10 @@ private async ValueTask RequestCoreAsync(bool isAsync, End
using (requestMessage?.Content ?? (IDisposable)Stream.Null)
{
- if (requestData.TcpStats)
+ if (requestData.EnableTcpStats)
tcpStats = TcpStats.GetStates();
- if (requestData.ThreadPoolStats)
+ if (requestData.EnableThreadPoolStats)
threadPoolStats = ThreadPoolStats.GetStats();
var prepareRequestMs = (Stopwatch.GetTimestamp() - beforeTicks) / (Stopwatch.Frequency / 1000);
diff --git a/src/Elastic.Transport/Components/TransportClient/HttpWebRequestInvoker.cs b/src/Elastic.Transport/Components/TransportClient/HttpWebRequestInvoker.cs
index d64c0cf..6a10c5c 100644
--- a/src/Elastic.Transport/Components/TransportClient/HttpWebRequestInvoker.cs
+++ b/src/Elastic.Transport/Components/TransportClient/HttpWebRequestInvoker.cs
@@ -125,10 +125,10 @@ private async ValueTask RequestCoreAsync(bool isAsync, End
//throw any errors if both are closed atleast one of them has to be Closed.
//Since we expose the stream we let closing the stream determining when to close the connection
- if (requestData.TcpStats)
+ if (requestData.EnableTcpStats)
tcpStats = TcpStats.GetStates();
- if (requestData.ThreadPoolStats)
+ if (requestData.EnableThreadPoolStats)
threadPoolStats = ThreadPoolStats.GetStats();
HttpWebResponse httpWebResponse;
@@ -332,7 +332,7 @@ private static HttpWebRequest CreateWebRequest(Endpoint endpoint, RequestData re
// on netstandard/netcoreapp2.0 this throws argument exception
request.MaximumResponseHeadersLength = -1;
#endif
- request.Pipelined = requestData.Pipelined;
+ request.Pipelined = requestData.HttpPipeliningEnabled;
if (requestData.TransferEncodingChunked)
request.SendChunked = true;
diff --git a/src/Elastic.Transport/Configuration/ITransportConfiguration.cs b/src/Elastic.Transport/Configuration/ITransportConfiguration.cs
index f8abe90..0cd334b 100644
--- a/src/Elastic.Transport/Configuration/ITransportConfiguration.cs
+++ b/src/Elastic.Transport/Configuration/ITransportConfiguration.cs
@@ -6,7 +6,6 @@
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net.Security;
-using System.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using Elastic.Transport.Products;
@@ -91,7 +90,7 @@ public interface ITransportConfiguration : IRequestConfiguration, IDisposable
Func? NodePredicate { get; }
///
- /// Allows you to register a callback every time a an API call is returned
+ /// Allows you to register a callback every time an API call is returned
///
Action? OnRequestCompleted { get; }
@@ -104,17 +103,17 @@ public interface ITransportConfiguration : IRequestConfiguration, IDisposable
///
/// When set will force all connections through this proxy
///
- string ProxyAddress { get; }
+ string? ProxyAddress { get; }
///
/// The password for the proxy, when configured
///
- string ProxyPassword { get; }
+ string? ProxyPassword { get; }
///
/// The username for the proxy, when configured
///
- string ProxyUsername { get; }
+ string? ProxyUsername { get; }
///
/// Append these query string parameters automatically to every request
@@ -127,19 +126,19 @@ public interface ITransportConfiguration : IRequestConfiguration, IDisposable
///
/// Register a ServerCertificateValidationCallback per request
///
- Func