/// <summary> /// Send request async. /// </summary> /// <param name="requestMessage"> /// The request message. /// </param> /// <param name="completionOption"> /// The completion option. /// </param> /// <returns> /// The <see cref="Task"/>. /// </returns> protected async Task<HttpResponseMessage> SendAsync( HttpRequestMessage requestMessage, HttpCompletionOption completionOption = HttpCompletionOption.ResponseHeadersRead) { Debug.Assert(this.Logger != null, "this.Logger != null"); Debug.Assert(this.HttpClient != null, "this.Logger != null"); try { if (this.Logger.IsDebugEnabled) { this.Logger.Debug("Send request ({0}): {1}.", requestMessage.Method, requestMessage.RequestUri); } HttpResponseMessage responseMessage = await this.HttpClient.SendAsync(requestMessage, completionOption); if (this.Logger.IsDebugEnabled) { await this.Logger.LogResponseAsync(requestMessage.RequestUri.ToString(), responseMessage); } return responseMessage; } catch (Exception exception) { this.Logger.Error(exception, "Exception while sending request, Method: {0}, Uri: {1}.", requestMessage.Method, requestMessage.RequestUri); throw; } }
public async Task SingleClient_ManyGets_Async(int numRequests, int dop, HttpCompletionOption completionOption) { string responseText = CreateResponse("abcdefghijklmnopqrstuvwxyz"); using (var client = new HttpClient()) { await ForCountAsync(numRequests, dop, i => CreateServerAndGetAsync(client, completionOption, responseText)); } }
private Task<HttpResponseMessage> sendHttpAsync(HttpClient client, HttpRequestMessage message, HttpCompletionOption completionOption, CancellationToken cancelationToken) { if (customMessageFunc == null) { customMessageFunc = buildHttpResponseMessage; } var task = Task.Run(customMessageFunc); return task; }
/// <summary> /// Custom implementation of the IHttpProvider.SendAsync method to handle retry logic /// </summary> /// <param name="request">The HTTP Request Message</param> /// <param name="completionOption">The completion option</param> /// <param name="cancellationToken">The cancellation token</param> /// <returns>The result of the asynchronous request</returns> /// <remarks>See here for further details: https://graph.microsoft.io/en-us/docs/overview/errors</remarks> Task<HttpResponseMessage> IHttpProvider.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) { Task<HttpResponseMessage> result = null; // Retry logic variables int retryAttempts = 0; int backoffInterval = this._delay; // Loop until we need to retry while (retryAttempts < this._retryCount) { try { // Make the request result = base.SendAsync(request, completionOption, cancellationToken); // And return the response in case of success return (result); } // Or handle any ServiceException catch (ServiceException ex) { // Check if the is an InnerException if (ex.InnerException != null) { // And if it is a WebException var wex = ex.InnerException as WebException; if (wex != null) { var response = wex.Response as HttpWebResponse; // Check if request was throttled - http status code 429 // Check is request failed due to server unavailable - http status code 503 if (response != null && (response.StatusCode == (HttpStatusCode)429 || response.StatusCode == (HttpStatusCode)503)) { Log.Warning(Constants.LOGGING_SOURCE, CoreResources.GraphExtensions_SendAsyncRetry, backoffInterval); //Add delay for retry Thread.Sleep(backoffInterval); //Add to retry count and increase delay. retryAttempts++; backoffInterval = backoffInterval * 2; } else { Log.Error(Constants.LOGGING_SOURCE, CoreResources.GraphExtensions_SendAsyncRetryException, wex.ToString()); throw; } } } throw; } } throw new MaximumRetryAttemptedException(string.Format("Maximum retry attempts {0}, has be attempted.", this._retryCount)); }
/// <summary> /// Creates and asynchronously sends an HttpRequestMethod, disposing HttpClient if AutoDispose it true. /// Mainly used to implement higher-level extension methods (GetJsonAsync, etc). /// </summary> /// <returns>A Task whose result is the received HttpResponseMessage.</returns> public async Task<HttpResponseMessage> SendAsync(HttpMethod verb, HttpContent content = null, CancellationToken? cancellationToken = null, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) { try { var request = new HttpRequestMessage(verb, this.Url) { Content = content }; request.SetFlurlSettings(this.Settings); return await HttpClient.SendAsync(request, completionOption, cancellationToken ?? CancellationToken.None); } finally { if (AutoDispose) Dispose(); } }
public void ManyClients_ManyGets(int numRequests, int dop, HttpCompletionOption completionOption) { string responseText = CreateResponse("abcdefghijklmnopqrstuvwxyz"); Parallel.For(0, numRequests, new ParallelOptions { MaxDegreeOfParallelism = dop, TaskScheduler = new ThreadPerTaskScheduler() }, _ => { using (var client = new HttpClient()) { CreateServerAndGet(client, completionOption, responseText); } }); }
/// <summary> /// Creates and asynchronously sends an HttpRequestMethod, disposing HttpClient if AutoDispose it true. /// Mainly used to implement higher-level extension methods (GetJsonAsync, etc). /// </summary> /// <returns>A Task whose result is the received HttpResponseMessage.</returns> public async Task<HttpResponseMessage> SendAsync(HttpMethod verb, HttpContent content = null, CancellationToken? cancellationToken = null, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) { try { var request = new HttpRequestMessage(verb, this.Url) { Content = content }; // mechanism for passing ad-hoc data to the MessageHandler request.Properties.Add("AllowedHttpStatusRanges", AllowedHttpStatusRanges); return await HttpClient.SendAsync(request, completionOption, cancellationToken ?? CancellationToken.None); } finally { if (AutoDispose) Dispose(); } }
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption) { //client.FollowRedirections = followRedirections; //try //{ return client.SendAsync(request, completionOption); //} //finally //{ // client.FollowRedirections = true; //} }
public static async Task<HttpResponseMessage> SendAsync(this HttpClient httpClient, HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken, Uri referrer, long? fromBytes, long? toBytes) { if (null != referrer) request.Headers.Referrer = referrer; if (null != fromBytes || null != toBytes) request.Headers.Range = new RangeHeaderValue(fromBytes, toBytes); return await httpClient.SendAsync(request, completionOption, cancellationToken).ConfigureAwait(false); }
public static async Task<HttpResponseMessage> SendAsync(this HttpClient httpClient, HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken, Uri referrer, long? fromBytes, long? toBytes) { if (null != referrer) request.Headers.Referer = referrer; if (null != fromBytes || null != toBytes) request.Headers["Range"] = new RangeHeaderValue(fromBytes, toBytes).ToString(); return await SendRequestAsync(httpClient, request, completionOption, cancellationToken); }
public static async Task<HttpResponseMessage> GetAsync(this HttpClient httpClient, Uri uri, HttpCompletionOption completionOption, CancellationToken cancellationToken) { try { return await httpClient.GetAsync(uri, completionOption).AsTask(cancellationToken).ConfigureAwait(false); } catch (Exception ex) { HttpClientExceptionTranslator.ThrowBetterHttpClientException(ex, cancellationToken); throw; } }
public static async Task<HttpResponseMessage> ExecuteAsync(this Uri uri, HttpMethod method, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead, double timeout = 100.0) { try { using (var client = new HttpClient()) { client.Timeout = TimeSpan.FromSeconds(timeout); return await client.SendAsync(new HttpRequestMessage(method, uri), completionOption); } } catch { return null; } }
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage message, HttpCompletionOption option, CancellationToken token) { #if NET_3_5 if(_connectionCount >= _connectionLimit) { return Task.Delay(500).ContinueWith(t => SendAsync(message, option, token)).Unwrap(); } Interlocked.Increment(ref _connectionCount); #else return _sendSemaphore?.WaitAsync()?.ContinueWith(t => { #endif var challengeResponseAuth = Authenticator as IChallengeResponseAuthenticator; if (challengeResponseAuth != null) { _authHandler.Borrow(x => x.Authenticator = challengeResponseAuth); challengeResponseAuth.PrepareWithRequest(message); } var httpClient = default(HttpClient); if(!_httpClient.AcquireTemp(out httpClient)) { return null; } (Authenticator as ICustomHeadersAuthorizer)?.AuthorizeRequest(message); return httpClient.SendAsync(message, option, token); #if !NET_3_5 })?.Unwrap()?.ContinueWith(t => { _sendSemaphore?.Release(); if(t.IsFaulted) { var e = t.Exception; if(Misc.UnwrapAggregate(e) is ObjectDisposedException) { return null; } throw e; } return t.Result; }); #endif }
protected void HandleByteArrayResponseRead(Action <HttpResponseMessage <byte[]> > responseCallback, HttpCompletionOption completionOption, int blockSize) { try { _response = (HttpWebResponse)_request.GetResponseAsync().Result; } catch (AggregateException e) { if (e.InnerExceptions.Any() && e.InnerExceptions.First() is WebException) { _response = (HttpWebResponse)(e.InnerExceptions.First() as WebException).Response; } else { throw; } } using (Stream stream = _response.GetResponseStream()) { if (responseCallback == null) { return; } long totalContentRead = 0; int contentReadThisRound = 0; int readThisLoop = 0; List <byte> allContent = new List <byte>(); byte[] buffer = new byte[blockSize]; do { readThisLoop = stream.Read(buffer, contentReadThisRound, blockSize - contentReadThisRound); contentReadThisRound += readThisLoop; if (contentReadThisRound == blockSize || readThisLoop == 0) { totalContentRead += contentReadThisRound; byte[] responseData = new byte[contentReadThisRound]; Array.Copy(buffer, responseData, contentReadThisRound); if (completionOption == HttpCompletionOption.AllResponseContent) { allContent.AddRange(responseData); } if (completionOption == HttpCompletionOption.StreamResponseContent || readThisLoop == 0) { RaiseResponseCallback(responseCallback, completionOption == HttpCompletionOption.AllResponseContent ? allContent.ToArray() : responseData, completionOption == HttpCompletionOption.AllResponseContent ? totalContentRead : contentReadThisRound, totalContentRead); } contentReadThisRound = 0; } } while (readThisLoop > 0); } }
private async Task <CustomHttpResponse <string> > ProcessRequest(RextOptions options) { if (this.Client == null) { throw new ArgumentNullException("HttpClient object cannot be null"); } // validate essential params if (string.IsNullOrEmpty(options.Url)) { if (string.IsNullOrEmpty(ConfigurationBundle.HttpConfiguration.BaseUrl)) { throw new ArgumentNullException(nameof(options.Url), $"{nameof(options.Url)} is required. Provide fully qualified api endpoint."); } else { throw new ArgumentNullException(nameof(options.Url), $"{nameof(options.Url)} is required. Provide the other part of api endpoint to match the BaseUrl."); } } if (options.Method == null) { throw new ArgumentNullException(nameof(options.Method), $"{nameof(options.Method)} is required. Use GET, POST etc.."); } if (string.IsNullOrEmpty(options.ContentType)) { throw new ArgumentNullException(nameof(options.ContentType), $"{nameof(options.ContentType) } is required. Use application/json, text.plain etc.."); } if (string.IsNullOrEmpty(options.ExpectedResponseFormat)) { throw new ArgumentNullException(nameof(options.ExpectedResponseFormat), $"{nameof(options.ExpectedResponseFormat)} is required. Use application/json, text.plain etc.."); } // execute all user actions pre-call ConfigurationBundle.BeforeCall?.Invoke(); var rsp = new CustomHttpResponse <string>(); var response = new HttpResponseMessage(); string responseString = string.Empty; try { Uri uri = options.CreateUri(ConfigurationBundle.HttpConfiguration.BaseUrl); if (uri == null) { throw new UriFormatException("Invalid request Uri"); } var requestMsg = new HttpRequestMessage(options.Method, uri); // set header if object has value if (this.Headers != null) { requestMsg.SetHeader(this.Headers); } if (options.Header != null) { requestMsg.SetHeader(options.Header); } if (ConfigurationBundle.HttpConfiguration.Header != null) { requestMsg.SetHeader(ConfigurationBundle.HttpConfiguration.Header); } if (!string.IsNullOrEmpty(options.ContentType)) { requestMsg.SetHeader("Accept", options.ExpectedResponseFormat); } // POST request if (options.Method != HttpMethod.Get && options.Payload != null) { string strPayload = string.Empty; if (options.IsForm) { strPayload = options.Payload.ToQueryString()?.TrimStart('?'); // form-data content post if (!options.IsUrlEncoded) { // handle multipart/form-data var formData = strPayload.Split('&'); var mpfDataBucket = new MultipartFormDataContent(); foreach (var i in formData) { var row = i.Split('='); if (row.Length == 2) // check index to avoid null { mpfDataBucket.Add(new StringContent(row[1]), row[0]); } } requestMsg.Content = mpfDataBucket; } else { // handle application/x-www-form-urlencoded requestMsg.Content = new StringContent(strPayload, Encoding.UTF8, "application/x-www-form-urlencoded"); } } else { // convert object to specified content-type if (options.ContentType == ContentType.Application_JSON) { strPayload = options.Payload.ToJson(); } else if (options.ContentType == ContentType.Application_XML) { strPayload = options.Payload.ToXml(); } else { strPayload = options.Payload.ToString(); } requestMsg.Content = new StringContent(strPayload, Encoding.UTF8, options.ContentType); } } // use stopwatch to monitor httpcall duration if (ConfigurationBundle.EnableStopwatch) { Stopwatch = new Stopwatch(); Stopwatch.Start(); } // check if HttpCompletionOption option is used HttpCompletionOption httpCompletionOption = ConfigurationBundle.HttpConfiguration.HttpCompletionOption; if (options.HttpCompletionOption.HasValue) { if (ConfigurationBundle.HttpConfiguration.HttpCompletionOption != options.HttpCompletionOption.Value) { httpCompletionOption = options.HttpCompletionOption.Value; } } response = await this.Client.SendAsync(requestMsg, httpCompletionOption, CancellationToken.None).ConfigureAwait(false); // set watch value to public member if (ConfigurationBundle.EnableStopwatch) { Stopwatch.Stop(); } rsp.StatusCode = response.StatusCode; if (options.IsStreamResponse) { var stream = await response.Content.ReadAsStreamAsync(); if (stream.Length > 0) { using (var rd = new StreamReader(stream)) responseString = rd.ReadToEnd(); } } else { responseString = await response.Content.ReadAsStringAsync(); } if (response.IsSuccessStatusCode) { rsp.Content = responseString; rsp.Message = "Http call successful"; } else { // this will always run before custom error-code actions // always set ThrowExceptionIfNotSuccessResponse=false if you will use custom error-code actions // perform checks for neccessary override bool throwExIfNotSuccessRsp = options.ThrowExceptionIfNotSuccessResponse ?? ConfigurationBundle.HttpConfiguration.ThrowExceptionIfNotSuccessResponse; if (throwExIfNotSuccessRsp) { throw new RextException($"Server response is {rsp.StatusCode}"); } if (response.StatusCode == System.Net.HttpStatusCode.NotFound) { rsp.Content = $"Url not found: {requestMsg.RequestUri}"; } else { rsp.Content = responseString; } rsp.Message = "Http call completed but not successful"; // handle code specific error from user int code = (int)response.StatusCode; if (code > 0 && ConfigurationBundle.StatusCodesToHandle != null && ConfigurationBundle.StatusCodesToHandle.Contains(code)) { ConfigurationBundle.OnStatusCode?.Invoke(ReturnStatusCode); } } // execute all user actions post-call ConfigurationBundle.AfterCall?.Invoke(); return(rsp); } catch (Exception ex) { // execute all user actions on error ConfigurationBundle.OnError?.Invoke(); if (ConfigurationBundle.SuppressRextExceptions) { if (ex?.Message.ToLower().Contains("a socket operation was attempted to an unreachable host") == true) { rsp.Message = "Network connection error"; } else if (ex?.Message.ToLower().Contains("the character set provided in contenttype is invalid") == true) { rsp.Message = "Invald response ContentType. If you are expecting a Stream response then set RextOptions.IsStreamResponse=true"; } else { rsp.Message = ex?.Message; //{ex?.InnerException?.Message ?? ex?.InnerException?.Message}"; } return(rsp); } else { throw ex; } } }
/// <summary>Send a GET request to the specified Uri with an HTTP completion option as an asynchronous operation.</summary> /// <returns>Returns <see cref="T:System.Threading.Tasks.Task`1" />.</returns> /// <param name="requestUri">The Uri the request is sent to.</param> /// <param name="completionOption">An HTTP completion option value that indicates when the operation should be considered completed.</param> /// <exception cref="T:System.ArgumentNullException">The <paramref name="requestUri" /> was null.</exception> public Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption) { return GetAsync(GetUri(requestUri), completionOption); }
// // Summary: // Send an HTTP request as an asynchronous operation. // // Parameters: // request: // The HTTP request message to send. // // completionOption: // When the operation should complete (as soon as a response is available or // after reading the whole response content). // // cancellationToken: // The cancellation token to cancel operation. // // Returns: // Returns System.Threading.Tasks.Task<TResult>.The task object representing // the asynchronous operation. // // Exceptions: // System.InvalidOperationException: // The request message was already sent by the System.Net.Http.HttpClient instance. public override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) { addHMACHeaders(request.RequestUri); return BaseClient.SendAsync(request, completionOption, cancellationToken); }
private async Task <HttpResponseMessage> InternalRequest(Uri requestUri, HttpMethod httpMethod, IReadOnlyCollection <KeyValuePair <string, string> > data = null, string referer = null, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead, byte maxRedirections = MaxTries) { if ((requestUri == null) || (httpMethod == null)) { ArchiLogger.LogNullError(nameof(requestUri) + " || " + nameof(httpMethod)); return(null); } HttpResponseMessage response; using (HttpRequestMessage request = new HttpRequestMessage(httpMethod, requestUri)) { if (data != null) { try { request.Content = new FormUrlEncodedContent(data); } catch (UriFormatException e) { ArchiLogger.LogGenericException(e); return(null); } } if (!string.IsNullOrEmpty(referer)) { request.Headers.Referrer = new Uri(referer); } try { response = await HttpClient.SendAsync(request, httpCompletionOption).ConfigureAwait(false); } catch (Exception e) { ArchiLogger.LogGenericDebuggingException(e); return(null); } } if (response == null) { return(null); } if (response.IsSuccessStatusCode) { return(response); } // WARNING: We still have undisposed response by now, make sure to dispose it ASAP if we're not returning it! if ((response.StatusCode >= HttpStatusCode.Ambiguous) && (response.StatusCode < HttpStatusCode.BadRequest) && (maxRedirections > 0)) { Uri redirectUri = response.Headers.Location; if (redirectUri.IsAbsoluteUri) { switch (redirectUri.Scheme) { case "http": case "https": break; case "steammobile": // Those redirections are invalid, but we're aware of that and we have extra logic for them return(response); default: // We have no clue about those, but maybe HttpClient can handle them for us ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(redirectUri.Scheme), redirectUri.Scheme)); break; } } else { redirectUri = new Uri(requestUri.GetLeftPart(UriPartial.Authority) + redirectUri); } response.Dispose(); return(await InternalRequest(redirectUri, httpMethod, data, referer, httpCompletionOption, --maxRedirections).ConfigureAwait(false)); } using (response) { if (Debugging.IsDebugBuild) { ArchiLogger.LogGenericDebug(string.Format(Strings.ErrorFailingRequest, requestUri)); ArchiLogger.LogGenericDebug(string.Format(Strings.StatusCode, response.StatusCode)); ArchiLogger.LogGenericDebug(string.Format(Strings.Content, await response.Content.ReadAsStringAsync().ConfigureAwait(false))); } return(null); } }
public HttpResponseMessage Send(HttpClient httpClient, HttpRequestMessage requestMessage, HttpCompletionOption httpCompletionOption) { return(httpClient.SendAsync(requestMessage, httpCompletionOption).WaitForTask()); }
/// <summary> /// PUTs the specified stream. /// </summary> /// <typeparam name="T">The type returned by the PUT call.</typeparam> /// <param name="squareLogo">The stream to PUT.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the request.</param> /// <param name="completionOption">The <see cref="HttpCompletionOption"/> to pass to the <see cref="IHttpProvider"/> on send.</param> /// <returns>The object returned by the PUT call.</returns> public System.Threading.Tasks.Task <T> PutAsync <T>(Stream squareLogo, CancellationToken cancellationToken, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) where T : OrganizationalBranding { this.ContentType = "application/octet-stream"; this.Method = "PUT"; return(this.SendAsync <T>(squareLogo, cancellationToken, completionOption)); }
/// <summary> /// Sends a request. /// </summary> /// <param name="request">The request.</param> /// <param name="completionOption">The completion option.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The response.</returns> public async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) { if (disableConnectionReuse) { using (var client = GetSingleUseClient()) { return(await client.SendAsync(request, completionOption, cancellationToken)); } } else { return(await client.SendAsync(request, completionOption, cancellationToken)); } }
public HttpResponseMessage Send(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) { return(SendAsync(request, completionOption, cancellationToken).Execute()); }
public HttpResponseMessage Get(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken) { return(GetAsync(requestUri, completionOption, cancellationToken).Execute()); }
public HttpResponseMessage Get(string requestUri, HttpCompletionOption completionOption) { return(GetAsync(requestUri, completionOption).Execute()); }
public override async Task <HttpResponseMessage> SendMessage(HttpRequestMessage message, bool authenticated = true, HttpCompletionOption completionOption = 0) { var resp = await base.SendMessage(message, authenticated, completionOption); //When a token expires it does forbidden instead of Unauthrorized if (resp.StatusCode == System.Net.HttpStatusCode.Forbidden) { //Lets refresh auth and try again await InvalidateCredentials(); await VerifyCredentials(); resp = await base.SendMessage(message, authenticated, completionOption); } return(resp); }
public async virtual Task <HttpResponseMessage> SendMessage(HttpRequestMessage message, bool authenticated = true, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) { if (authenticated) { await VerifyCredentials(); } return(await Client.SendAsync(message, completionOption)); }
public async Task <HttpResponseMessage> SendMessage(string path, HttpContent content, HttpMethod method, Dictionary <string, string> headers = null, bool authenticated = true, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) { if (authenticated) { await VerifyCredentials(); } path = await PrepareUrl(path); var uri = BaseAddress != null ? new Uri(BaseAddress, path.TrimStart('/')) : new Uri(path); var request = new HttpRequestMessage { Method = method, RequestUri = uri, Content = content, }; MergeHeaders(request.Headers, headers); return(await SendMessage(request, authenticated, completionOption)); }
public Task<HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken) { return GetAsync(CreateUri(requestUri), completionOption, cancellationToken); }
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption) { return SendAsync(request, completionOption, CancellationToken.None); }
/// <summary> /// Send retriable GET request to the specified parameters as an asynchronous operation. /// </summary> /// <param name="requestUri">The Uri the request is sent to.</param> /// <param name="completionOption">An HTTP completion option value that indicates when the operation should be considered completed.</param> /// <param name="tryCount">Max try count if SuccessStatusCode equal to false</param> /// <param name="interval">Interval between calls in millisecond</param> /// <returns></returns> public static async Task <HttpResponseMessage> RetryGetAsync(this HttpClient httpClient, Uri requestUri, HttpCompletionOption completionOption, int tryCount, int interval = 0) { return(await RetryProvider.Retry (async() => await httpClient.GetAsync(requestUri, completionOption), tryCount, interval)); }
async public Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) { //throw new NotImplementedException("implement type check in serialized to make sure that requestcs are for TResult on DummyGraphClient"); this.RequestCaptured(this, await GraphNetworkHelpers.CloneHttpRequestMessageAsync(request)); return(new HttpResponseMessage(System.Net.HttpStatusCode.OK)); }
public async Task <IBoxResponse <T> > ExecuteAsync <T>(IBoxRequest request) where T : class { // Need to account for special cases when the return type is a stream bool isStream = typeof(T) == typeof(Stream); var numRetries = 3; try { // TODO: yhu@ better handling of different request var isMultiPartRequest = request.GetType() == typeof(BoxMultiPartRequest); var isBinaryRequest = request.GetType() == typeof(BoxBinaryRequest); while (true) { HttpRequestMessage httpRequest = null; if (isMultiPartRequest) { httpRequest = BuildMultiPartRequest(request as BoxMultiPartRequest); } else if (isBinaryRequest) { httpRequest = BuildBinaryRequest(request as BoxBinaryRequest); } else { httpRequest = BuildRequest(request); } // Add headers foreach (var kvp in request.HttpHeaders) { // They could not be added to the headers directly if (kvp.Key == Constants.RequestParameters.ContentMD5 || kvp.Key == Constants.RequestParameters.ContentRange) { httpRequest.Content.Headers.Add(kvp.Key, kvp.Value); } else { httpRequest.Headers.TryAddWithoutValidation(kvp.Key, kvp.Value); } } // If we are retrieving a stream, we should return without reading the entire response HttpCompletionOption completionOption = isStream ? HttpCompletionOption.ResponseHeadersRead : HttpCompletionOption.ResponseContentRead; Debug.WriteLine(string.Format("RequestUri: {0}", httpRequest.RequestUri));//, RequestHeader: {1} , httpRequest.Headers.Select(i => string.Format("{0}:{1}", i.Key, i.Value)).Aggregate((i, j) => i + "," + j))); HttpClient client = CreateClient(request); BoxResponse <T> boxResponse = new BoxResponse <T>(); HttpResponseMessage response = await client.SendAsync(httpRequest, completionOption).ConfigureAwait(false); // If we get a 429 error code and this is not a multi part request (meaning a file upload, which cannot be retried // because the stream cannot be reset) and we haven't exceeded the number of allowed retries, then retry the request. if ((response.StatusCode == TooManyRequests && !isMultiPartRequest) && numRetries-- > 0) { //need to wait for Retry-After seconds and then retry request var retryAfterHeader = response.Headers.RetryAfter; TimeSpan delay; if (retryAfterHeader.Delta.HasValue) { delay = retryAfterHeader.Delta.Value; } else { delay = TimeSpan.FromMilliseconds(2000); } Debug.WriteLine("TooManyRequests error (429). Waiting for {0} seconds to retry request. RequestUri: {1}", delay.Seconds, httpRequest.RequestUri); await CrossPlatform.Delay(Convert.ToInt32(delay.TotalMilliseconds)); } else { boxResponse.Headers = response.Headers; // Translate the status codes that interest us boxResponse.StatusCode = response.StatusCode; switch (response.StatusCode) { case HttpStatusCode.OK: case HttpStatusCode.Created: case HttpStatusCode.NoContent: case HttpStatusCode.Found: boxResponse.Status = ResponseStatus.Success; break; case HttpStatusCode.Accepted: boxResponse.Status = ResponseStatus.Pending; break; case HttpStatusCode.Unauthorized: boxResponse.Status = ResponseStatus.Unauthorized; break; case HttpStatusCode.Forbidden: boxResponse.Status = ResponseStatus.Forbidden; break; case TooManyRequests: boxResponse.Status = ResponseStatus.TooManyRequests; break; default: boxResponse.Status = ResponseStatus.Error; break; } if (isStream && boxResponse.Status == ResponseStatus.Success) { var resObj = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); boxResponse.ResponseObject = resObj as T; } else { boxResponse.ContentString = await response.Content.ReadAsStringAsync().ConfigureAwait(false); } return(boxResponse); } } } catch (Exception ex) { Debug.WriteLine(string.Format("Exception: {0}", ex.Message)); throw; } }
/// <summary> /// Gets the stream. /// </summary> /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the request.</param> /// <param name="completionOption">The <see cref="HttpCompletionOption"/> to pass to the <see cref="IHttpProvider"/> on send.</param> /// <returns>The stream.</returns> public System.Threading.Tasks.Task <Stream> GetAsync(CancellationToken cancellationToken, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) { this.Method = "GET"; return(this.SendStreamRequestAsync(null, cancellationToken, completionOption)); }
private async Task <HttpResponseMessage> InternalRequest(Uri requestUri, HttpMethod httpMethod, IReadOnlyCollection <KeyValuePair <string, string> > data = null, string referer = null, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead, byte maxRedirections = MaxTries) { if ((requestUri == null) || (httpMethod == null)) { ArchiLogger.LogNullError(nameof(requestUri) + " || " + nameof(httpMethod)); return(null); } HttpResponseMessage response; using (HttpRequestMessage request = new HttpRequestMessage(httpMethod, requestUri)) { #if !NETFRAMEWORK request.Version = HttpClient.DefaultRequestVersion; #endif if (data != null) { try { request.Content = new FormUrlEncodedContent(data); } catch (UriFormatException) { request.Content = new StringContent(string.Join("&", data.Select(kv => WebUtility.UrlEncode(kv.Key) + "=" + WebUtility.UrlEncode(kv.Value))), null, "application/x-www-form-urlencoded"); } } if (!string.IsNullOrEmpty(referer)) { request.Headers.Referrer = new Uri(referer); } if (Debugging.IsUserDebugging) { ArchiLogger.LogGenericDebug(httpMethod + " " + requestUri); } try { response = await HttpClient.SendAsync(request, httpCompletionOption).ConfigureAwait(false); } catch (Exception e) { ArchiLogger.LogGenericDebuggingException(e); return(null); } } if (response == null) { if (Debugging.IsUserDebugging) { ArchiLogger.LogGenericDebug("null <- " + httpMethod + " " + requestUri); } return(null); } if (Debugging.IsUserDebugging) { ArchiLogger.LogGenericDebug(response.StatusCode + " <- " + httpMethod + " " + requestUri); } if (response.IsSuccessStatusCode) { return(response); } // WARNING: We still have not disposed response by now, make sure to dispose it ASAP if we're not returning it! if ((response.StatusCode >= HttpStatusCode.Ambiguous) && (response.StatusCode < HttpStatusCode.BadRequest) && (maxRedirections > 0)) { Uri redirectUri = response.Headers.Location; if (redirectUri.IsAbsoluteUri) { switch (redirectUri.Scheme) { case "http": case "https": break; case "steammobile": // Those redirections are invalid, but we're aware of that and we have extra logic for them return(response); default: // We have no clue about those, but maybe HttpClient can handle them for us ASF.ArchiLogger.LogGenericError(string.Format(Strings.WarningUnknownValuePleaseReport, nameof(redirectUri.Scheme), redirectUri.Scheme)); break; } } else { redirectUri = new Uri(requestUri, redirectUri); } response.Dispose(); // Per https://tools.ietf.org/html/rfc7231#section-7.1.2, a redirect location without a fragment should inherit the fragment from the original URI if (!string.IsNullOrEmpty(requestUri.Fragment) && string.IsNullOrEmpty(redirectUri.Fragment)) { redirectUri = new UriBuilder(redirectUri) { Fragment = requestUri.Fragment }.Uri; } return(await InternalRequest(redirectUri, httpMethod, data, referer, httpCompletionOption, --maxRedirections).ConfigureAwait(false)); } if (response.StatusCode.IsClientErrorCode()) { if (Debugging.IsUserDebugging) { ArchiLogger.LogGenericDebug(string.Format(Strings.Content, await response.Content.ReadAsStringAsync().ConfigureAwait(false))); } // Do not retry on client errors return(response); } using (response) { if (Debugging.IsUserDebugging) { ArchiLogger.LogGenericDebug(string.Format(Strings.Content, await response.Content.ReadAsStringAsync().ConfigureAwait(false))); } return(null); } }
private async Task<HttpResponseMessage> RequestInnerAsync( TimeSpan? requestTimeout, HttpCompletionOption completionOption, CancellationToken cancellationToken, HttpMethod method, string path, HttpContent content = null, IDictionary<string, string> extraParams = null, bool includeAuthToQuery = true) { HttpClient client = GetHttpClient(); if (requestTimeout.HasValue) { client.Timeout = requestTimeout.Value; } StringBuilder uri = BuildUri(path, extraParams, includeAuthToQuery); HttpRequestMessage request = BuildRequest(method, content, uri); #if DEBUG Debug.WriteLine("[Request] {0}", request.ToJson()); if (content != null) { Debug.WriteLine("[RequestData] {0}", content.ReadAsStringAsync().Result); } #endif return await client.SendAsync(request, completionOption, cancellationToken); }
private static void CreateServerAndGet(HttpClient client, HttpCompletionOption completionOption, string responseText) { LoopbackServer.CreateServerAsync((server, url) => { Task<HttpResponseMessage> getAsync = client.GetAsync(url, completionOption); LoopbackServer.AcceptSocketAsync(server, (s, stream, reader, writer) => { while (!string.IsNullOrEmpty(reader.ReadLine())) ; writer.Write(responseText); writer.Flush(); s.Shutdown(SocketShutdown.Send); return Task.CompletedTask; }).GetAwaiter().GetResult(); getAsync.GetAwaiter().GetResult().Dispose(); return Task.CompletedTask; }).GetAwaiter().GetResult(); }
private async Task<HttpResponseMessage> MakeRequestInnerAsync(TimeSpan? requestTimeout, HttpCompletionOption completionOption, HttpMethod method, string path, IQueryString queryString, IDictionary<string, string> headers, IRequestContent data, CancellationToken cancellationToken) { HttpClient client = this.GetHttpClient(); if (requestTimeout.HasValue) { client.Timeout = requestTimeout.Value; } HttpRequestMessage request = PrepareRequest(method, path, queryString, headers, data); return await client.SendAsync(request, completionOption, cancellationToken); }
private async Task <HttpResponseMessage> InternalGet(string request, string referer = null, HttpCompletionOption httpCompletionOptions = HttpCompletionOption.ResponseContentRead) { if (string.IsNullOrEmpty(request)) { ArchiLogger.LogNullError(nameof(request)); return(null); } return(await InternalRequest(new Uri(request), HttpMethod.Get, null, referer, httpCompletionOptions).ConfigureAwait(false)); }
public Task <HttpResponseMessage> GetAsync(string requestUri, HttpCompletionOption completionOption) { return(SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri), completionOption)); }
public static Task <JObject> GetJObjectAsync(this IFlurlRequest request, CancellationToken cancellationToken = default, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) => (request ?? throw new ArgumentNullException(nameof(request)))
public async Task <HttpResponseMessage> SendAsync(HttpMethod method, Uri url, HttpCompletionOption httpCompletionOption = HttpCompletionOption.ResponseContentRead, byte[] content = null) { HttpRequestMessage request = new HttpRequestMessage(method, url); AddRequestHeaders(request); HttpResponseMessage response = null; try { if (content != null) { request.Content = new ByteArrayContent(content); } response = await _httpClient.SendAsync(request, httpCompletionOption); if (!response.IsSuccessStatusCode) { await LogNonSuccessAsync(response); } } catch (Exception ex) { throw new HttpRequestException("Request failed for: " + url.AbsolutePath, ex); } return(response); }
public Task<HttpResponseMessage> GetAsync (string requestUri, HttpCompletionOption completionOption) { return SendAsync (new HttpRequestMessage (HttpMethod.Get, requestUri), completionOption); }
private async Task<HttpResponseMessage> SendRequestAsync( Stream stream, CancellationToken cancellationToken, HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead) { if (string.IsNullOrEmpty(this.RequestUrl)) { throw new ArgumentNullException(nameof(this.RequestUrl), "Session Upload URL cannot be null or empty."); } if (this.Client.AuthenticationProvider == null) { throw new ArgumentNullException(nameof(this.Client.AuthenticationProvider), "Client.AuthenticationProvider must not be null."); } using (var request = this.GetHttpRequestMessage()) { await this.Client.AuthenticationProvider.AuthenticateRequestAsync(request).ConfigureAwait(false); request.Content = new StreamContent(stream); request.Content.Headers.ContentRange = new ContentRangeHeaderValue(this.RangeBegin, this.RangeEnd, this.TotalSessionLength); request.Content.Headers.ContentLength = this.RangeLength; return await this.Client.HttpProvider.SendAsync(request, completionOption, cancellationToken).ConfigureAwait(false); } }
async Task<HttpResponseMessage> SendAsyncWorker (HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) { using (var lcts = CancellationTokenSource.CreateLinkedTokenSource (cts.Token, cancellationToken)) { lcts.CancelAfter (timeout); var task = base.SendAsync (request, lcts.Token); if (task == null) throw new InvalidOperationException ("Handler failed to return a value"); var response = await task.ConfigureAwait (false); if (response == null) throw new InvalidOperationException ("Handler failed to return a response"); // // Read the content when default HttpCompletionOption.ResponseContentRead is set // if (response.Content != null && (completionOption & HttpCompletionOption.ResponseHeadersRead) == 0) { await response.Content.LoadIntoBufferAsync (MaxResponseContentBufferSize).ConfigureAwait (false); } return response; } }
private static async Task CreateServerAndGetAsync(HttpClient client, HttpCompletionOption completionOption, string responseText) { await LoopbackServer.CreateServerAsync(async (server, url) => { Task<HttpResponseMessage> getAsync = client.GetAsync(url, completionOption); await LoopbackServer.AcceptSocketAsync(server, async (s, stream, reader, writer) => { while (!string.IsNullOrEmpty(await reader.ReadLineAsync().ConfigureAwait(false))) ; await writer.WriteAsync(responseText).ConfigureAwait(false); await writer.FlushAsync().ConfigureAwait(false); s.Shutdown(SocketShutdown.Send); }); (await getAsync.ConfigureAwait(false)).Dispose(); }); }
public async ValueTask <HttpResponseMessage> SendAsync(HttpRequestMessage requestMessage, HttpCompletionOption completionOption = HttpCompletionOption.ResponseHeadersRead, System.Threading.CancellationToken cancellationToken = default) { // Write request message headers _messageWriter.WriteMessage(requestMessage, _connection.Transport.Output); // Write the body directly if (requestMessage.Content != null) { await requestMessage.Content.CopyToAsync(_connection.Transport.Output.AsStream()).ConfigureAwait(false); } await _connection.Transport.Output.FlushAsync(cancellationToken).ConfigureAwait(false); var content = new HttpBodyContent(); var headerReader = new Http1ResponseMessageReader(content); var result = await _reader.ReadAsync(headerReader, cancellationToken).ConfigureAwait(false); if (result.IsCompleted) { throw new ConnectionAbortedException(); } var response = result.Message; // TODO: Handle upgrade if (content.Headers.ContentLength != null) { content.SetStream(new HttpBodyStream(_reader, new ContentLengthHttpBodyReader(response.Content.Headers.ContentLength.Value))); } else if (response.Headers.TransferEncodingChunked.HasValue) { content.SetStream(new HttpBodyStream(_reader, new ChunkedHttpBodyReader())); } else { content.SetStream(new HttpBodyStream(_reader, new ContentLengthHttpBodyReader(0))); } _reader.Advance(); return(response); }
public Task <HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken) { return(SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri), completionOption, cancellationToken)); }
public virtual async Task <HttpResponseMessage> SendAsync(HttpRequest httpRequest, HttpCompletionOption completionOption, CancellationToken cancellationToken = default) { ThrowIfDisposed(); OnBeforeSend(httpRequest); using (var message = CreateHttpRequestMessage(httpRequest)) { var response = await HttpClient.SendAsync(message, completionOption, cancellationToken).ForAwait(); if (ShouldFollowResponse(response)) { using (var followMessage = CreateHttpRequestMessage(httpRequest)) { followMessage.RequestUri = response.Headers.Location; return(await HttpClient.SendAsync(followMessage, completionOption, cancellationToken).ForAwait()); } } OnAfterSend(response); return(response); } }
public Task<HttpResponseMessage> SendAsync (HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) { if (request == null) throw new ArgumentNullException ("request"); if (request.SetIsUsed ()) throw new InvalidOperationException ("Cannot send the same request message multiple times"); if (request.RequestUri == null) { if (base_address == null) throw new InvalidOperationException ("The request URI must either be an absolute URI or BaseAddress must be set"); request.RequestUri = base_address; } else if (!request.RequestUri.IsAbsoluteUri) { if (base_address == null) throw new InvalidOperationException ("The request URI must either be an absolute URI or BaseAddress must be set"); request.RequestUri = new Uri (base_address, request.RequestUri); } if (headers != null) { request.Headers.AddHeaders (headers); } return SendAsyncWorker (request, completionOption, cancellationToken); }
public Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption) { return(SendAsync(request, completionOption, CancellationToken.None)); }
public virtual async Task<HttpResponseMessage> SendAsync(HttpRequest httpRequest, HttpCompletionOption completionOption, CancellationToken cancellationToken) { ThrowIfDisposed(); OnBeforeSend(httpRequest); using (var message = CreateHttpRequestMessage(httpRequest)) { var response = await HttpClient.SendAsync(message, completionOption, cancellationToken).ForAwait(); if (ShouldFollowResponse(response)) { using (var followMessage = CreateHttpRequestMessage(httpRequest)) { followMessage.RequestUri = response.Headers.Location; return await HttpClient.SendAsync(followMessage, completionOption, cancellationToken).ForAwait(); } } OnAfterSend(response); return response; } }
public void OnResponse(HttpClient httpClient, HttpRequestMessage request, HttpResponseMessage response, HttpCompletionOption completionOption, CancellationToken cancellationToken) { response.StatusCode = HttpStatusCode.Accepted; }
public virtual async Task<HttpResponseMessage> SendAsync(HttpRequest httpRequest, HttpCompletionOption completionOption, CancellationToken cancellationToken) { return await HttpClient.SendAsync(OnBeforeSend(httpRequest), completionOption, cancellationToken).ForAwait(); }
public void OnRequest(HttpClient httpClient, HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) { }
public Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption) { return GetAsync(requestUri, completionOption, CancellationToken.None); }
internal Task <HttpResponseMessage> SendAsyncRequest(HttpRequestMessage message, HttpCompletionOption option, CancellationToken token) { var client = default(CouchbaseLiteHttpClient); if (_client.AcquireTemp(out client)) { foreach (var header in RequestHeaders) { var str = header.Value as string; if (str != null) { message.Headers.Add(header.Key, str); } } return(client.SendAsync(message, option, token)); } else { Log.To.Sync.W(Tag, "Aborting message sent after disposal"); } return(null); }
public Task<HttpResponseMessage> GetAsync(Uri requestUri, HttpCompletionOption completionOption, CancellationToken cancellationToken) { return SendAsync(new HttpRequestMessage(HttpMethod.Get, requestUri), completionOption, cancellationToken); }
public async Task <IBoxResponse <T> > ExecuteAsync <T>(IBoxRequest request) where T : class { // Need to account for special cases when the return type is a stream bool isStream = typeof(T) == typeof(Stream); HttpRequestMessage httpRequest = request.GetType() == typeof(BoxMultiPartRequest) ? BuildMultiPartRequest(request as BoxMultiPartRequest) : BuildRequest(request); // Add headers foreach (var kvp in request.HttpHeaders) { httpRequest.Headers.TryAddWithoutValidation(kvp.Key, kvp.Value); } // If we are retrieving a stream, we should return without reading the entire response HttpCompletionOption completionOption = isStream ? HttpCompletionOption.ResponseHeadersRead : HttpCompletionOption.ResponseContentRead; Debug.WriteLine(string.Format("RequestUri: {0}", httpRequest.RequestUri));//, RequestHeader: {1} , httpRequest.Headers.Select(i => string.Format("{0}:{1}", i.Key, i.Value)).Aggregate((i, j) => i + "," + j))); try { HttpClient client = CreateClient(request); HttpResponseMessage response = await client.SendAsync(httpRequest, completionOption).ConfigureAwait(false); BoxResponse <T> boxResponse = new BoxResponse <T>(); boxResponse.Headers = response.Headers; // Translate the status codes that interest us boxResponse.StatusCode = response.StatusCode; switch (response.StatusCode) { case HttpStatusCode.OK: case HttpStatusCode.Created: case HttpStatusCode.NoContent: boxResponse.Status = ResponseStatus.Success; break; case HttpStatusCode.Accepted: boxResponse.Status = ResponseStatus.Pending; break; case HttpStatusCode.Unauthorized: boxResponse.Status = ResponseStatus.Unauthorized; break; default: boxResponse.Status = ResponseStatus.Error; break; } if (isStream && boxResponse.Status == ResponseStatus.Success) { var resObj = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); boxResponse.ResponseObject = resObj as T; } else { boxResponse.ContentString = await response.Content.ReadAsStringAsync().ConfigureAwait(false); } return(boxResponse); } catch (Exception ex) { Debug.WriteLine(string.Format("Exception: {0}", ex.Message)); throw; } }
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken) { if (request == null) { throw new ArgumentNullException(nameof(request)); } CheckDisposed(); CheckRequestMessage(request); SetOperationStarted(); PrepareRequestMessage(request); // PrepareRequestMessage will resolve the request address against the base address. // We need a CancellationTokenSource to use with the request. We always have the global // _pendingRequestsCts to use, plus we may have a token provided by the caller, and we may // have a timeout. If we have a timeout or a caller-provided token, we need to create a new // CTS (we can't, for example, timeout the pending requests CTS, as that could cancel other // unrelated operations). Otherwise, we can use the pending requests CTS directly. CancellationTokenSource cts; bool disposeCts; bool hasTimeout = _timeout != s_infiniteTimeout; if (hasTimeout || cancellationToken.CanBeCanceled) { disposeCts = true; cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _pendingRequestsCts.Token); if (hasTimeout) { cts.CancelAfter(_timeout); } } else { disposeCts = false; cts = _pendingRequestsCts; } // Initiate the send Task<HttpResponseMessage> sendTask = base.SendAsync(request, cts.Token); return completionOption == HttpCompletionOption.ResponseContentRead ? FinishSendAsyncBuffered(sendTask, request, cts, disposeCts) : FinishSendAsyncUnbuffered(sendTask, request, cts, disposeCts); }
protected void HandleByteArrayResponseRead(Action <HttpResponseMessage <byte[]> > responseCallback, HttpCompletionOption completionOption, int blockSize) { HttpWebResponse response = (HttpWebResponse)_request.GetResponse(); _response = response; using (Stream stream = response.GetResponseStream()) { if (responseCallback == null) { return; } long totalContentRead = 0; int contentReadThisRound = 0; int readThisLoop = 0; List <byte> allContent = new List <byte>(); do { byte[] buffer = new byte[blockSize]; readThisLoop = stream.Read(buffer, contentReadThisRound, blockSize - contentReadThisRound); contentReadThisRound += readThisLoop; if (contentReadThisRound == blockSize || readThisLoop == 0) { totalContentRead += contentReadThisRound; byte[] responseData = null; if (buffer.Length > contentReadThisRound) { responseData = new byte[contentReadThisRound]; Array.Copy(buffer, responseData, contentReadThisRound); } else { responseData = buffer; } if (completionOption == HttpCompletionOption.AllResponseContent) { allContent.AddRange(responseData); } if (completionOption == HttpCompletionOption.StreamResponseContent || readThisLoop == 0) { RaiseResponseCallback(responseCallback, completionOption == HttpCompletionOption.AllResponseContent ? allContent.ToArray() : responseData, completionOption == HttpCompletionOption.AllResponseContent ? totalContentRead : contentReadThisRound, totalContentRead); } contentReadThisRound = 0; } } while (readThisLoop > 0); } }