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));
            }
        }
Example #5
0
        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;
                }
            }
        }
Example #6
0
        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));
        }
Example #9
0
 public override Task <ElasticsearchResponse <TReturn> > RequestAsync <TReturn>(RequestData requestData) =>
 Task.FromResult(this.ReturnConnectionStatus <TReturn>(requestData));
Example #10
0
        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;
			}
Example #17
0
 public virtual Task <ElasticsearchResponse <TReturn> > RequestAsync <TReturn>(RequestData requestData) where TReturn : class =>
 Task.FromResult(this.ReturnConnectionStatus <TReturn>(requestData));
Example #18
0
 public override ElasticsearchResponse <TReturn> Request <TReturn>(RequestData requestData) =>
 this.ReturnConnectionStatus <TReturn>(requestData);
Example #19
0
        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());
        }
Example #21
0
        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);
            }
        }
Example #22
0
        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;
 }
Example #24
0
        // 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))}";
        }
Example #25
0
        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;
        }
Example #26
0
        // 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);
        }
Example #27
0
        /// <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));
        }
Example #28
0
        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);
        }
Example #29
0
        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);
            }
        }
Example #31
0
 private static void RegisterApmTaskTimeout(IAsyncResult result, WebRequest request, RequestData requestData) =>
 ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, TimeoutCallback, request, requestData.RequestTimeout, true);
Example #32
0
        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;
			}