public Task <HttpResponseMessage> SendAsync(PrtgRequestMessage request, CancellationToken token) { //Cannot use HttpCompletionOption.ResponseHeadersRead without manually disposing //HttpResponseMessage objects, which will also dispose internal stream. Existing code //needs to be refactored to have the deserialization happen in a callback to ExecuteRequest //so that there is no problem wrapping the HttpResponseMessage up in a using for both //sync/async return(asyncClient.GetAsync(request.Url, token)); }
private void HandleSocketException(Exception ex, PrtgRequestMessage request) { var socketException = ex?.InnerException as SocketException; if (socketException != null) { var port = socketException.Message.Substring(socketException.Message.LastIndexOf(':') + 1); var protocol = request.Url.Substring(0, request.Url.IndexOf(':')).ToUpper(); if (socketException.SocketErrorCode == SocketError.TimedOut) { throw new TimeoutException($"Connection timed out while communicating with remote server via {protocol} on port {port}. Confirm server address and port are valid and PRTG Service is running.", ex); } else if (socketException.SocketErrorCode == SocketError.ConnectionRefused) { throw new WebException($"Server rejected {protocol} connection on port {port}. Please confirm expected server protocol and port, PRTG Core Service is running and that any SSL certificate is trusted.", ex); } } }
public Task <HttpResponseMessage> SendSync(PrtgRequestMessage request, CancellationToken token) { return(SendAsync(request, token)); }
private bool HandleRequestException(Exception innerMostEx, Exception fallbackHandlerEx, PrtgRequestMessage request, ref int retriesRemaining, Action thrower, CancellationToken token) { if (innerMostEx != null) //Synchronous + Asynchronous { if (retriesRemaining > 0) { prtgClient.HandleEvent(prtgClient.retryRequest, new RetryRequestEventArgs(innerMostEx, request.Url, retriesRemaining)); } else { HandleSocketException(innerMostEx, request); throw innerMostEx; } } else { if (fallbackHandlerEx != null && retriesRemaining > 0) { prtgClient.HandleEvent(prtgClient.retryRequest, new RetryRequestEventArgs(fallbackHandlerEx, request.Url, retriesRemaining)); } else { thrower?.Invoke(); return(false); } } if (retriesRemaining > 0) { var attemptsMade = prtgClient.RetryCount - retriesRemaining + 1; var delay = prtgClient.RetryDelay * attemptsMade; //Note that we don't have an asynchronous wait for the asynchronous version, //as this causes weird timing issues in tests like PrtgClient_RetriesWhileStreaming, //where the final retry occurs after StreamSensors has supposedly completed token.WaitHandle.WaitOne(delay * 1000); } retriesRemaining--; return(true); }
private async Task <PrtgResponse> ExecuteRequestAsync(PrtgRequestMessage request, CancellationToken token, Func <HttpResponseMessage, Task <PrtgResponse> > responseParser = null) { prtgClient.Log($"Asynchronously executing request {request}", LogLevel.Request); int retriesRemaining = prtgClient.RetryCount; do { try { if (token == CancellationToken.None && DefaultCancellationToken != CancellationToken.None) { token = DefaultCancellationToken; } var responseMessage = await webClient.SendAsync(request, token).ConfigureAwait(false); PrtgResponse responseContent = null; if (responseParser != null) { responseContent = await responseParser(responseMessage).ConfigureAwait(false); } if (responseContent == null) { responseContent = await GetAppropriateResponseAsync(responseMessage, prtgClient.LogLevel).ConfigureAwait(false); } //If we needed to log response, GetAppropriateResponseAsync will have handled this if (responseContent.Type == PrtgResponseType.String) { prtgClient.Log(responseContent.StringValue, LogLevel.Response); } ValidateHttpResponse(responseMessage, responseContent); return(responseContent); } catch (HttpRequestException ex) { var inner = ex.InnerException as WebException; var result = HandleRequestException(inner, ex, request, ref retriesRemaining, null, token); if (!result) { throw; } } catch (TaskCanceledException ex) { //If the token we specified was cancelled, throw the TaskCanceledException if (token.IsCancellationRequested) { throw; } //Otherwise, a token that was created internally for use with timing out was cancelled, so throw a timeout exception throw new TimeoutException($"The server timed out while executing request.", ex); } } while (true); //Keep retrying as long as we have retries remaining }
private PrtgResponse ExecuteRequest(PrtgRequestMessage request, CancellationToken token, Func <HttpResponseMessage, PrtgResponse> responseParser = null) { prtgClient.Log($"Synchronously executing request {request}", LogLevel.Request); int retriesRemaining = prtgClient.RetryCount; do { try { if (token == CancellationToken.None && DefaultCancellationToken != CancellationToken.None) { token = DefaultCancellationToken; } var responseMessage = webClient.SendSync(request, token).Result; PrtgResponse responseContent = null; if (responseParser != null) { responseContent = responseParser(responseMessage); } if (responseContent == null) { responseContent = GetAppropriateResponse(responseMessage, prtgClient.LogLevel); } //If we needed to log response, GetAppropriateResponse will have handled this if (responseContent.Type == PrtgResponseType.String) { prtgClient.Log(responseContent.StringValue, LogLevel.Response); } ValidateHttpResponse(responseMessage, responseContent); return(responseContent); } catch (Exception ex) when(ex is AggregateException || ex is TaskCanceledException || ex is HttpRequestException) { var innerException = ex.InnerException; if (innerException is TaskCanceledException) { //If the token we specified was cancelled, throw the TaskCanceledException if (token.IsCancellationRequested) { throw innerException; } //Otherwise, a token that was created internally for use with timing out was cancelled, so throw a timeout exception innerException = new TimeoutException($"The server timed out while executing request.", ex.InnerException); } var result = HandleRequestException(ex.InnerException?.InnerException, innerException, request, ref retriesRemaining, () => { if (innerException != null) { throw innerException; } }, token); if (!result) { throw; } } } while (true); //Keep retrying as long as we have retries remaining }
private bool HandleRequestException(Exception innerMostEx, Exception fallbackHandlerEx, PrtgRequestMessage request, ref int retriesRemaining, Action thrower) { if (innerMostEx != null) //Synchronous + Asynchronous { if (retriesRemaining > 0) { prtgClient.HandleEvent(prtgClient.retryRequest, new RetryRequestEventArgs(innerMostEx, request.Url, retriesRemaining)); } else { HandleSocketException(innerMostEx, request); throw innerMostEx; } } else { if (fallbackHandlerEx != null && retriesRemaining > 0) { prtgClient.HandleEvent(prtgClient.retryRequest, new RetryRequestEventArgs(fallbackHandlerEx, request.Url, retriesRemaining)); } else { thrower?.Invoke(); return(false); } } if (retriesRemaining > 0) { var attemptsMade = prtgClient.RetryCount - retriesRemaining + 1; var delay = prtgClient.RetryDelay * attemptsMade; Thread.Sleep(delay * 1000); } retriesRemaining--; return(true); }