private async Task AssertRegularResponse(bool disableDirectStreaming, Action<ResponseBuilder<RootNodeInfoResponse>> mutate = null) { var settings = disableDirectStreaming ? _settingsDisableDirectStream : _settings; var memoryStreamFactory = new TrackMemoryStreamFactory(); var requestData = new RequestData(HttpMethod.GET, "/", null, settings, null, memoryStreamFactory) { Node = new Node(new Uri("http://localhost:9200")) }; var responseBuilder = new ResponseBuilder<RootNodeInfoResponse>(requestData) { }; mutate?.Invoke(responseBuilder); var stream = new TrackDisposeStream(); responseBuilder.Stream = stream; var response = responseBuilder.ToResponse(); memoryStreamFactory.Created.Count().Should().Be(disableDirectStreaming ? 1 : 0); if (disableDirectStreaming) { var memoryStream = memoryStreamFactory.Created[0]; memoryStream.IsDisposed.Should().BeTrue(); } stream.IsDisposed.Should().BeTrue(); stream = new TrackDisposeStream(); responseBuilder.Stream = stream; response = await responseBuilder.ToResponseAsync(); memoryStreamFactory.Created.Count().Should().Be(disableDirectStreaming ? 2 : 0); if (disableDirectStreaming) { var memoryStream = memoryStreamFactory.Created[1]; memoryStream.IsDisposed.Should().BeTrue(); } stream.IsDisposed.Should().BeTrue(); }
public void BadResponse <TResponse>(ref TResponse response, IApiCallDetails callDetails, RequestData data, ElasticsearchClientException exception) where TResponse : class, IElasticsearchResponse, new() { if (response == null) { //make sure we copy over the error body in case we disabled direct streaming. var s = callDetails?.ResponseBodyInBytes == null ? Stream.Null : new MemoryStream(callDetails.ResponseBodyInBytes); var m = callDetails?.ResponseMimeType ?? RequestData.MimeType; response = ResponseBuilder.ToResponse <TResponse>(data, exception, callDetails?.HttpStatusCode, null, s, m); } response.ApiCall.AuditTrail = this.AuditTrail; }
public virtual async Task <ElasticsearchResponse <TReturn> > RequestAsync <TReturn>(RequestData requestData, CancellationToken cancellationToken) where TReturn : class { var builder = new ResponseBuilder <TReturn>(requestData, cancellationToken); Action unregisterWaitHandle = null; try { var data = requestData.PostData; var request = this.CreateHttpWebRequest(requestData); using (cancellationToken.Register(() => request.Abort())) { if (data != null) { var apmGetRequestStreamTask = Task.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, null); unregisterWaitHandle = RegisterApmTaskTimeout(apmGetRequestStreamTask, request, requestData); using (var stream = await apmGetRequestStreamTask.ConfigureAwait(false)) { if (requestData.HttpCompression) { using (var zipStream = new GZipStream(stream, CompressionMode.Compress)) await data.WriteAsync(zipStream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false); } else { await data.WriteAsync(stream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false); } } unregisterWaitHandle?.Invoke(); } requestData.MadeItToResponse = true; //http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.getresponsestream.aspx //Either the stream or the response object needs to be closed but not both although it won't //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 var apmGetResponseTask = Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null); unregisterWaitHandle = RegisterApmTaskTimeout(apmGetResponseTask, request, requestData); var response = (HttpWebResponse)(await apmGetResponseTask.ConfigureAwait(false)); builder.StatusCode = (int)response.StatusCode; builder.Stream = response.GetResponseStream(); if (response.SupportsHeaders && response.Headers.HasKeys() && response.Headers.AllKeys.Contains("Warning")) { builder.DeprecationWarnings = response.Headers.GetValues("Warning"); } // https://github.com/elastic/elasticsearch-net/issues/2311 // if stream is null call dispose on response instead. if (builder.Stream == null || builder.Stream == Stream.Null) { response.Dispose(); } } } catch (WebException e) { HandleException(builder, e); } finally { unregisterWaitHandle?.Invoke(); } return(await builder.ToResponseAsync().ConfigureAwait(false)); }
protected virtual void SetBasicAuthenticationIfNeeded(HttpWebRequest request, RequestData requestData) { // Basic auth credentials take the following precedence (highest -> lowest): // 1 - Specified on the request (highest precedence) // 2 - Specified at the global IConnectionSettings level // 3 - Specified with the URI (lowest precedence) var userInfo = Uri.UnescapeDataString(requestData.Uri.UserInfo); if (requestData.BasicAuthorizationCredentials != null) { userInfo = requestData.BasicAuthorizationCredentials.ToString(); } if (!userInfo.IsNullOrEmpty()) { request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(userInfo)); } }
public async Task <ElasticsearchResponse <TReturn> > CallElasticsearchAsync <TReturn>(RequestData requestData) where TReturn : class { using (var audit = this.Audit(HealthyResponse)) { audit.Node = requestData.Node; audit.Path = requestData.Path; ElasticsearchResponse <TReturn> response = null; try { response = await this._connection.RequestAsync <TReturn>(requestData).ConfigureAwait(false); response.AuditTrail = this.AuditTrail; ThrowBadAuthPipelineExceptionWhenNeeded(response); if (!response.Success) { audit.Event = AuditEvent.BadResponse; } return(response); } catch (Exception e) { (response as ElasticsearchResponse <Stream>)?.Body?.Dispose(); audit.Event = AuditEvent.BadResponse; audit.Exception = e; throw; } } }
public ElasticsearchClientException CreateClientException <TResponse>( TResponse response, IApiCallDetails callDetails, RequestData data, List <PipelineException> pipelineExceptions ) where TResponse : class, IElasticsearchResponse, new() { if (callDetails?.Success ?? false) { return(null); } var innerException = pipelineExceptions.HasAny() ? pipelineExceptions.AsAggregateOrFirst() : callDetails?.OriginalException; var statusCode = callDetails?.HttpStatusCode != null?callDetails.HttpStatusCode.Value.ToString() : "unknown"; var resource = callDetails == null ? "unknown resource" : $"Status code {statusCode} from: {callDetails.HttpMethod} {callDetails.Uri.PathAndQuery}"; var exceptionMessage = innerException?.Message ?? "Request failed to execute"; var pipelineFailure = data.OnFailurePipelineFailure; if (pipelineExceptions.HasAny()) { pipelineFailure = pipelineExceptions.Last().FailureReason; } if (IsTakingTooLong) { pipelineFailure = PipelineFailure.MaxTimeoutReached; Audit(MaxTimeoutReached); exceptionMessage = "Maximum timeout reached while retrying request"; } else if (Retried >= MaxRetries && MaxRetries > 0) { pipelineFailure = PipelineFailure.MaxRetriesReached; Audit(MaxRetriesReached); exceptionMessage = "Maximum number of retries reached"; var now = _dateTimeProvider.Now(); var activeNodes = _connectionPool.Nodes.Count(n => n.IsAlive || n.DeadUntil <= now); if (Retried >= activeNodes) { Audit(FailedOverAllNodes); exceptionMessage += ", failed over to all the known alive nodes before failing"; } } exceptionMessage += $". Call: {resource}"; if (response != null && response.TryGetServerErrorReason(out var reason)) { exceptionMessage += $". ServerError: {reason}"; } var clientException = new ElasticsearchClientException(pipelineFailure, exceptionMessage, innerException) { Request = data, Response = callDetails, AuditTrail = AuditTrail }; return(clientException); }
public ResponseBuilder(RequestData requestData, CancellationToken cancellationToken = default(CancellationToken)) { _requestData = requestData; _cancellationToken = cancellationToken; }
public virtual async Task <TResponse> RequestAsync <TResponse>(RequestData requestData, CancellationToken cancellationToken) where TResponse : class, IElasticsearchResponse, new() { Action unregisterWaitHandle = null; int? statusCode = null; IEnumerable <string> warnings = null; Stream responseStream = null; Exception ex = null; string mimeType = null; try { var data = requestData.PostData; var request = this.CreateHttpWebRequest(requestData); using (cancellationToken.Register(() => request.Abort())) { if (data != null) { var apmGetRequestStreamTask = Task.Factory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, null); unregisterWaitHandle = RegisterApmTaskTimeout(apmGetRequestStreamTask, request, requestData); using (var stream = await apmGetRequestStreamTask.ConfigureAwait(false)) { if (requestData.HttpCompression) { using (var zipStream = new GZipStream(stream, CompressionMode.Compress)) await data.WriteAsync(zipStream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false); } else { await data.WriteAsync(stream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false); } } unregisterWaitHandle?.Invoke(); } requestData.MadeItToResponse = true; //http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.getresponsestream.aspx //Either the stream or the response object needs to be closed but not both although it won't //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 var apmGetResponseTask = Task.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null); unregisterWaitHandle = RegisterApmTaskTimeout(apmGetResponseTask, request, requestData); var response = (HttpWebResponse)(await apmGetResponseTask.ConfigureAwait(false)); HandleResponse(response, out statusCode, out responseStream, out mimeType); if (response.SupportsHeaders && response.Headers.HasKeys() && response.Headers.AllKeys.Contains("Warning")) { warnings = response.Headers.GetValues("Warning"); } } } catch (WebException e) { ex = e; if (e.Response is HttpWebResponse response) { HandleResponse(response, out statusCode, out responseStream, out mimeType); } } finally { unregisterWaitHandle?.Invoke(); } responseStream = responseStream ?? Stream.Null; return(await ResponseBuilder.ToResponseAsync <TResponse> (requestData, ex, statusCode, warnings, responseStream, mimeType, cancellationToken) .ConfigureAwait(false)); }
public override Task <ElasticsearchResponse <TReturn> > RequestAsync <TReturn>(RequestData requestData) => Task.FromResult(this.ReturnConnectionStatus <TReturn>(requestData));
public virtual async Task <ElasticsearchResponse <TReturn> > RequestAsync <TReturn>(RequestData requestData, CancellationToken cancellationToken) where TReturn : class { var client = this.GetClient(requestData); var builder = new ResponseBuilder <TReturn>(requestData, cancellationToken); try { var requestMessage = CreateHttpRequestMessage(requestData); var response = await client.SendAsync(requestMessage, cancellationToken).ConfigureAwait(false); requestData.MadeItToResponse = true; builder.StatusCode = (int)response.StatusCode; IEnumerable <string> warnings; if (response.Headers.TryGetValues("Warning", out warnings)) { builder.DeprecationWarnings = warnings; } if (response.Content != null) { builder.Stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); } } catch (HttpRequestException e) { builder.Exception = e; } return(await builder.ToResponseAsync().ConfigureAwait(false)); }
public T CallElasticsearch <T>(RequestData requestData) { return(default);
protected async Task <ElasticsearchResponse <TReturn> > ReturnConnectionStatusAsync <TReturn>(RequestData requestData, CancellationToken cancellationToken, byte[] responseBody = null, int?statusCode = null) where TReturn : class { var body = responseBody ?? _responseBody; var data = requestData.PostData; if (data != null) { using (var stream = new MemoryStream()) { if (requestData.HttpCompression) { using (var zipStream = new GZipStream(stream, CompressionMode.Compress)) await data.WriteAsync(zipStream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false); } else { await data.WriteAsync(stream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false); } } } requestData.MadeItToResponse = true; var builder = new ResponseBuilder <TReturn>(requestData) { StatusCode = statusCode ?? this._statusCode, Stream = (body != null) ? new MemoryStream(body) : null, Exception = _exception }; var cs = await builder.ToResponseAsync().ConfigureAwait(false); return(cs); }
public virtual ElasticsearchResponse <TReturn> Request <TReturn>(RequestData requestData) where TReturn : class => this.ReturnConnectionStatus <TReturn>(requestData);
public virtual async Task <ElasticsearchResponse <TReturn> > RequestAsync <TReturn>(RequestData requestData, CancellationToken cancellationToken) where TReturn : class => await this.ReturnConnectionStatusAsync <TReturn>(requestData, cancellationToken).ConfigureAwait(false);
public virtual async Task <ElasticsearchResponse <TReturn> > RequestAsync <TReturn>(RequestData requestData) where TReturn : class { var client = this.GetClient(requestData); var builder = new ResponseBuilder <TReturn>(requestData); try { var requestMessage = CreateHttpRequestMessage(requestData); var response = await client.SendAsync(requestMessage, requestData.CancellationToken).ConfigureAwait(false); builder.StatusCode = (int)response.StatusCode; if (response.Content != null) { builder.Stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); } } catch (HttpRequestException e) { builder.Exception = e; } return(await builder.ToResponseAsync().ConfigureAwait(false)); }
protected override void AlterServicePoint(ServicePoint requestServicePoint, RequestData requestData) { base.AlterServicePoint(requestServicePoint, requestData); requestServicePoint.ConnectionLimit = 10000; requestServicePoint.UseNagleAlgorithm = true; }
public virtual Task <ElasticsearchResponse <TReturn> > RequestAsync <TReturn>(RequestData requestData) where TReturn : class => Task.FromResult(this.ReturnConnectionStatus <TReturn>(requestData));
public override ElasticsearchResponse <TReturn> Request <TReturn>(RequestData requestData) => this.ReturnConnectionStatus <TReturn>(requestData);
protected virtual void SetBasicAuthenticationIfNeeded(HttpRequestMessage requestMessage, RequestData requestData) { string userInfo = null; if (!requestData.Uri.UserInfo.IsNullOrEmpty()) { userInfo = Uri.UnescapeDataString(requestData.Uri.UserInfo); } else if (requestData.BasicAuthorizationCredentials != null) { userInfo = requestData.BasicAuthorizationCredentials.ToString(); } if (!userInfo.IsNullOrEmpty()) { var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes(userInfo)); requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials); } }
public virtual async Task <ElasticsearchResponse <TReturn> > RequestAsync <TReturn>(RequestData requestData) where TReturn : class { var builder = new ResponseBuilder <TReturn>(requestData); try { var request = this.CreateHttpWebRequest(requestData); var data = requestData.PostData; if (data != null) { using (var stream = await request.GetRequestStreamAsync()) { if (requestData.HttpCompression) { using (var zipStream = new GZipStream(stream, CompressionMode.Compress)) await data.WriteAsync(zipStream, requestData.ConnectionSettings); } else { await data.WriteAsync(stream, requestData.ConnectionSettings); } } } //http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.getresponsestream.aspx //Either the stream or the response object needs to be closed but not both although it won't //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 var response = (HttpWebResponse)(await request.GetResponseAsync()); builder.StatusCode = (int)response.StatusCode; builder.Stream = response.GetResponseStream(); } catch (WebException e) { HandleException(builder, e); } return(await builder.ToResponseAsync()); }
public ElasticsearchResponse <TReturn> Request <TReturn>(HttpMethod method, string path, PostData <object> data = null, IRequestParameters requestParameters = null) where TReturn : class { using (var pipeline = this.PipelineProvider.Create(this.Settings, this.DateTimeProvider, this.MemoryStreamFactory, requestParameters)) { pipeline.FirstPoolUsage(this.Settings.BootstrapLock); var requestData = new RequestData(method, path, data, this.Settings, requestParameters, this.MemoryStreamFactory); this.Settings.OnRequestDataCreated?.Invoke(requestData); ElasticsearchResponse <TReturn> response = null; var seenExceptions = new List <PipelineException>(); foreach (var node in pipeline.NextNode()) { requestData.Node = node; try { pipeline.SniffOnStaleCluster(); Ping(pipeline, node); response = pipeline.CallElasticsearch <TReturn>(requestData); if (!response.SuccessOrKnownError) { pipeline.MarkDead(node); pipeline.SniffOnConnectionFailure(); } } catch (PipelineException pipelineException) when(!pipelineException.Recoverable) { pipeline.MarkDead(node); seenExceptions.Add(pipelineException); break; } catch (PipelineException pipelineException) { pipeline.MarkDead(node); seenExceptions.Add(pipelineException); } catch (ResolveException) { throw; } catch (Exception killerException) { throw new UnexpectedElasticsearchClientException(killerException, seenExceptions) { Request = requestData, Response = response, AuditTrail = pipeline?.AuditTrail }; } if (response != null && response.SuccessOrKnownError) { pipeline.MarkAlive(node); break; } } if (response == null || !response.Success) { pipeline.BadResponse(ref response, requestData, seenExceptions); } this.Settings.OnRequestCompleted?.Invoke(response); return(response); } }
public virtual async Task <TResponse> RequestAsync <TResponse>(RequestData requestData, CancellationToken cancellationToken ) where TResponse : class, IElasticsearchResponse, new() { Action unregisterWaitHandle = null; int? statusCode = null; IEnumerable <string> warnings = null; Stream responseStream = null; Exception ex = null; string mimeType = null; ReadOnlyDictionary <TcpState, int> tcpStats = null; ReadOnlyDictionary <string, ThreadPoolStatistics> threadPoolStats = null; try { var data = requestData.PostData; var request = CreateHttpWebRequest(requestData); using (cancellationToken.Register(() => request.Abort())) { if (data != null) { var apmGetRequestStreamTask = Task.Factory.FromAsync <Stream>(request.BeginGetRequestStream, r => request.EndGetRequestStream(r), null); unregisterWaitHandle = RegisterApmTaskTimeout(apmGetRequestStreamTask, request, requestData); using (var stream = await apmGetRequestStreamTask.ConfigureAwait(false)) { if (requestData.HttpCompression) { using (var zipStream = new GZipStream(stream, CompressionMode.Compress)) await data.WriteAsync(zipStream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false); } else { await data.WriteAsync(stream, requestData.ConnectionSettings, cancellationToken).ConfigureAwait(false); } } unregisterWaitHandle?.Invoke(); } requestData.MadeItToResponse = true; //http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.getresponsestream.aspx //Either the stream or the response object needs to be closed but not both although it won't //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 var apmGetResponseTask = Task.Factory.FromAsync(request.BeginGetResponse, r => request.EndGetResponse(r), null); unregisterWaitHandle = RegisterApmTaskTimeout(apmGetResponseTask, request, requestData); if (requestData.TcpStats) { tcpStats = TcpStats.GetStates(); } if (requestData.ThreadPoolStats) { threadPoolStats = ThreadPoolStats.GetStats(); } var httpWebResponse = (HttpWebResponse)await apmGetResponseTask.ConfigureAwait(false); HandleResponse(httpWebResponse, out statusCode, out responseStream, out mimeType); if (httpWebResponse.SupportsHeaders && httpWebResponse.Headers.HasKeys() && httpWebResponse.Headers.AllKeys.Contains("Warning")) { warnings = httpWebResponse.Headers.GetValues("Warning"); } } } catch (WebException e) { ex = e; if (e.Response is HttpWebResponse httpWebResponse) { HandleResponse(httpWebResponse, out statusCode, out responseStream, out mimeType); } } finally { unregisterWaitHandle?.Invoke(); } responseStream ??= Stream.Null; var response = await ResponseBuilder.ToResponseAsync <TResponse> (requestData, ex, statusCode, warnings, responseStream, mimeType, cancellationToken) .ConfigureAwait(false); // set TCP and threadpool stats on the response here so that in the event the request fails after the point of // gathering stats, they are still exposed on the call details. Ideally these would be set inside ResponseBuilder.ToResponse, // but doing so would be a breaking change in 7.x response.ApiCall.TcpStats = tcpStats; response.ApiCall.ThreadPoolStats = threadPoolStats; return(response); }
public ResponseBuilder(RequestData requestData) { _requestData = requestData; }
// TODO - make private in 8.0 and only expose SetAuthenticationIfNeeded protected virtual void SetBasicAuthenticationIfNeeded(HttpWebRequest request, RequestData requestData) { // Basic auth credentials take the following precedence (highest -> lowest): // 1 - Specified on the request (highest precedence) // 2 - Specified at the global IConnectionSettings level // 3 - Specified with the URI (lowest precedence) string userInfo = null; if (!string.IsNullOrEmpty(requestData.Uri.UserInfo)) { userInfo = Uri.UnescapeDataString(requestData.Uri.UserInfo); } else if (requestData.BasicAuthorizationCredentials != null) { userInfo = $"{requestData.BasicAuthorizationCredentials.Username}:{requestData.BasicAuthorizationCredentials.Password.CreateString()}"; } if (string.IsNullOrWhiteSpace(userInfo)) { return; } request.Headers["Authorization"] = $"Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes(userInfo))}"; }
public void BadResponse <TReturn>(ref ElasticsearchResponse <TReturn> response, RequestData data, List <PipelineException> pipelineExceptions) where TReturn : class { var callDetails = response ?? pipelineExceptions.LastOrDefault()?.Response; var pipelineFailure = PipelineFailure.BadResponse; if (pipelineExceptions.HasAny()) { pipelineFailure = pipelineExceptions.Last().FailureReason; } var innerException = pipelineExceptions.HasAny() ? new AggregateException(pipelineExceptions) : callDetails?.OriginalException; var exceptionMessage = innerException?.Message ?? "Could not complete the request to Elasticsearch."; if (this.IsTakingTooLong) { pipelineFailure = PipelineFailure.MaxTimeoutReached; this.Audit(MaxTimeoutReached); exceptionMessage = "Maximum timout reached while retrying request"; } else if (this.Retried >= this.MaxRetries && this.MaxRetries > 0) { pipelineFailure = PipelineFailure.MaxRetriesReached; this.Audit(MaxRetriesReached); exceptionMessage = "Maximum number of retries reached."; } var clientException = new ElasticsearchClientException(pipelineFailure, exceptionMessage, innerException) { Request = data, Response = callDetails, AuditTrail = this.AuditTrail }; if (_settings.ThrowExceptions) { this._settings.OnRequestCompleted?.Invoke(clientException.Response); throw clientException; } if (response == null) { response = new ResponseBuilder <TReturn>(data) { StatusCode = callDetails?.HttpStatusCode, Exception = clientException }.ToResponse(); } if (callDetails?.ResponseBodyInBytes != null && response.ResponseBodyInBytes == null) { response.ResponseBodyInBytes = callDetails.ResponseBodyInBytes; } if (callDetails?.ServerError != null && response.ServerError == null) { response.ServerError = callDetails.ServerError; } response.AuditTrail = this.AuditTrail; }
// TODO - make private in 8.0 and only expose SetAuthenticationIfNeeded protected virtual bool SetApiKeyAuthenticationIfNeeded(HttpWebRequest request, RequestData requestData) { // ApiKey auth credentials take the following precedence (highest -> lowest): // 1 - Specified on the request (highest precedence) // 2 - Specified at the global IConnectionSettings level string apiKey = null; if (requestData.ApiKeyAuthenticationCredentials != null) { apiKey = requestData.ApiKeyAuthenticationCredentials.Base64EncodedApiKey.CreateString(); } if (string.IsNullOrWhiteSpace(apiKey)) { return(false); } request.Headers["Authorization"] = $"ApiKey {apiKey}"; return(true); }
/// <summary> /// Registers an APM async task cancellation on the threadpool /// </summary> /// <returns>An unregister action that can be used to remove the waithandle prematurely</returns> private static Action RegisterApmTaskTimeout(IAsyncResult result, WebRequest request, RequestData requestData) { var waitHandle = result.AsyncWaitHandle; var registeredWaitHandle = ThreadPool.RegisterWaitForSingleObject(waitHandle, TimeoutCallback, request, requestData.RequestTimeout, true); return(() => registeredWaitHandle?.Unregister(waitHandle)); }
public virtual TResponse Request <TResponse>(RequestData requestData) where TResponse : class, IElasticsearchResponse, new() { int?statusCode = null; IEnumerable <string> warnings = null; Stream responseStream = null; Exception ex = null; string mimeType = null; ReadOnlyDictionary <TcpState, int> tcpStats = null; ReadOnlyDictionary <string, ThreadPoolStatistics> threadPoolStats = null; try { var request = CreateHttpWebRequest(requestData); var data = requestData.PostData; if (data != null) { using (var stream = request.GetRequestStream()) { if (requestData.HttpCompression) { using (var zipStream = new GZipStream(stream, CompressionMode.Compress)) data.Write(zipStream, requestData.ConnectionSettings); } else { data.Write(stream, requestData.ConnectionSettings); } } } requestData.MadeItToResponse = true; if (requestData.TcpStats) { tcpStats = TcpStats.GetStates(); } if (requestData.ThreadPoolStats) { threadPoolStats = ThreadPoolStats.GetStats(); } //http://msdn.microsoft.com/en-us/library/system.net.httpwebresponse.getresponsestream.aspx //Either the stream or the response object needs to be closed but not both although it won't //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 var httpWebResponse = (HttpWebResponse)request.GetResponse(); HandleResponse(httpWebResponse, out statusCode, out responseStream, out mimeType); //response.Headers.HasKeys() can return false even if response.Headers.AllKeys has values. if (httpWebResponse.SupportsHeaders && httpWebResponse.Headers.Count > 0 && httpWebResponse.Headers.AllKeys.Contains("Warning")) { warnings = httpWebResponse.Headers.GetValues("Warning"); } } catch (WebException e) { ex = e; if (e.Response is HttpWebResponse httpWebResponse) { HandleResponse(httpWebResponse, out statusCode, out responseStream, out mimeType); } } responseStream ??= Stream.Null; var response = ResponseBuilder.ToResponse <TResponse>(requestData, ex, statusCode, warnings, responseStream, mimeType); // set TCP and threadpool stats on the response here so that in the event the request fails after the point of // gathering stats, they are still exposed on the call details. Ideally these would be set inside ResponseBuilder.ToResponse, // but doing so would be a breaking change in 7.x response.ApiCall.TcpStats = tcpStats; response.ApiCall.ThreadPoolStats = threadPoolStats; return(response); }
protected virtual void SetServerCertificateValidationCallBackIfNeeded(HttpWebRequest request, RequestData requestData) { var callback = requestData?.ConnectionSettings?.ServerCertificateValidationCallback; #if !__MonoCS__ //Only assign if one is defined on connection settings and a subclass has not already set one if (callback != null && request.ServerCertificateValidationCallback == null) { request.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(callback); } #else if (callback != null) { throw new Exception("Mono misses ServerCertificateValidationCallback on HttpWebRequest"); } #endif }
public async Task <ElasticsearchResponse <TReturn> > RequestAsync <TReturn>(HttpMethod method, string path, CancellationToken cancellationToken, PostData <object> data = null, IRequestParameters requestParameters = null) where TReturn : class { using (var pipeline = this.PipelineProvider.Create(this.Settings, this.DateTimeProvider, this.MemoryStreamFactory, requestParameters)) { await pipeline.FirstPoolUsageAsync(this.Settings.BootstrapLock, cancellationToken).ConfigureAwait(false); var requestData = new RequestData(method, path, data, this.Settings, requestParameters, this.MemoryStreamFactory); this.Settings.OnRequestDataCreated?.Invoke(requestData); ElasticsearchResponse <TReturn> response = null; var seenExceptions = new List <PipelineException>(); foreach (var node in pipeline.NextNode()) { requestData.Node = node; try { await pipeline.SniffOnStaleClusterAsync(cancellationToken).ConfigureAwait(false); await PingAsync(pipeline, node, cancellationToken).ConfigureAwait(false); response = await pipeline.CallElasticsearchAsync <TReturn>(requestData, cancellationToken).ConfigureAwait(false); if (!response.SuccessOrKnownError) { pipeline.MarkDead(node); await pipeline.SniffOnConnectionFailureAsync(cancellationToken).ConfigureAwait(false); } } catch (PipelineException pipelineException) when(!pipelineException.Recoverable) { pipeline.MarkDead(node); seenExceptions.Add(pipelineException); break; } catch (PipelineException pipelineException) { pipeline.MarkDead(node); seenExceptions.Add(pipelineException); } catch (Exception killerException) { throw new UnexpectedElasticsearchClientException(killerException, seenExceptions) { Request = requestData, Response = response, AuditTrail = pipeline.AuditTrail }; } if (response == null || !response.SuccessOrKnownError) { continue; } pipeline.MarkAlive(node); break; } if (requestData.Node == null) //foreach never ran { pipeline.ThrowNoNodesAttempted(requestData, seenExceptions); } if (response == null || !response.Success) { pipeline.BadResponse(ref response, requestData, seenExceptions); } this.Settings.OnRequestCompleted?.Invoke(response); return(response); } }
private static void RegisterApmTaskTimeout(IAsyncResult result, WebRequest request, RequestData requestData) => ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, TimeoutCallback, request, requestData.RequestTimeout, true);
public async Task <TResponse> RequestAsync <TResponse>(HttpMethod method, string path, CancellationToken cancellationToken, PostData data = null, IRequestParameters requestParameters = null ) where TResponse : class, IElasticsearchResponse, new() { using (var pipeline = PipelineProvider.Create(Settings, DateTimeProvider, MemoryStreamFactory, requestParameters)) { await pipeline.FirstPoolUsageAsync(Settings.BootstrapLock, cancellationToken).ConfigureAwait(false); var requestData = new RequestData(method, path, data, Settings, requestParameters, MemoryStreamFactory); Settings.OnRequestDataCreated?.Invoke(requestData); TResponse response = null; var seenExceptions = new List <PipelineException>(); foreach (var node in pipeline.NextNode()) { requestData.Node = node; try { await pipeline.SniffOnStaleClusterAsync(cancellationToken).ConfigureAwait(false); await PingAsync(pipeline, node, cancellationToken).ConfigureAwait(false); response = await pipeline.CallElasticsearchAsync <TResponse>(requestData, cancellationToken).ConfigureAwait(false); if (!response.ApiCall.SuccessOrKnownError) { pipeline.MarkDead(node); await pipeline.SniffOnConnectionFailureAsync(cancellationToken).ConfigureAwait(false); } } catch (PipelineException pipelineException) when(!pipelineException.Recoverable) { HandlePipelineException(ref response, pipelineException, pipeline, node, seenExceptions); break; } catch (PipelineException pipelineException) { HandlePipelineException(ref response, pipelineException, pipeline, node, seenExceptions); } catch (Exception killerException) { throw new UnexpectedElasticsearchClientException(killerException, seenExceptions) { Request = requestData, Response = response?.ApiCall, AuditTrail = pipeline.AuditTrail }; } if (cancellationToken.IsCancellationRequested) { pipeline.AuditCancellationRequested(); break; } if (response == null || !response.ApiCall.SuccessOrKnownError) { continue; } pipeline.MarkAlive(node); break; } return(FinalizeResponse(requestData, pipeline, seenExceptions, response)); } }
protected bool Equals(RequestData other) => RequestTimeout.Equals(other.RequestTimeout) && PingTimeout.Equals(other.PingTimeout) && KeepAliveTime == other.KeepAliveTime && KeepAliveInterval == other.KeepAliveInterval && Pipelined == other.Pipelined && HttpCompression == other.HttpCompression && Equals(Headers, other.Headers) && string.Equals(ProxyAddress, other.ProxyAddress) && string.Equals(ProxyUsername, other.ProxyUsername) && string.Equals(ProxyPassword, other.ProxyPassword) && DisableAutomaticProxyDetection == other.DisableAutomaticProxyDetection && Equals(BasicAuthorizationCredentials, other.BasicAuthorizationCredentials) && Equals(ConnectionSettings, other.ConnectionSettings) && Equals(MemoryStreamFactory, other.MemoryStreamFactory);
protected override HttpClientHandler CreateHttpClientHandler(RequestData requestData) { var handler = base.CreateHttpClientHandler(requestData); handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, errors) => true; return handler; }