/// <summary> /// Given an IRequestInfo, construct a HttpRequestMessage, send it, check the response for success, then return it /// </summary> /// <param name="requestInfo">IRequestInfo to construct the request from</param> /// <param name="readBody">True to pass HttpCompletionOption.ResponseContentRead, meaning that the body is read here</param> /// <returns>Resulting HttpResponseMessage</returns> protected virtual async Task <HttpResponseMessage> SendRequestAsync(IRequestInfo requestInfo, bool readBody) { var path = this.SubstitutePathParameters(requestInfo) ?? String.Empty; var message = new HttpRequestMessage() { Method = requestInfo.Method, RequestUri = this.ConstructUri(path, requestInfo), Content = this.ConstructContent(requestInfo), }; this.ApplyHttpRequestMessageProperties(requestInfo, message); // Do this after setting the content, as doing so may set headers which we want to remove / override this.ApplyHeaders(requestInfo, message); // If we're deserializing, we're always going to want the content, since we're always going to deserialize it. // Therefore use HttpCompletionOption.ResponseContentRead so that the content gets read at this point, meaning // that it can be cancelled by our CancellationToken. // However if we're returning a HttpResponseMessage, that's probably because the user wants to read it themselves. // They might want to only fetch the first bit, or stream it into a file, or get process on it. In this case, // we'll want HttpCompletionOption.ResponseHeadersRead. var completionOption = readBody ? HttpCompletionOption.ResponseContentRead : HttpCompletionOption.ResponseHeadersRead; var response = await this.httpClient.SendAsync(message, completionOption, requestInfo.CancellationToken).ConfigureAwait(false); if (!response.IsSuccessStatusCode && !requestInfo.AllowAnyStatusCode) { throw await ApiException.CreateAsync(message, response).ConfigureAwait(false); } return(response); }
/// <summary> /// Given an IRequestInfo, construct a HttpRequestMessage, send it, check the response for success, then return it /// </summary> /// <param name="requestInfo">IRequestInfo to construct the request from</param> /// <returns>Resulting HttpResponseMessage</returns> protected virtual async Task <HttpResponseMessage> SendRequestAsync(IRequestInfo requestInfo) { var path = this.SubstitutePathParameters(requestInfo) ?? String.Empty; var message = new HttpRequestMessage() { Method = requestInfo.Method, RequestUri = this.ConstructUri(path, requestInfo), Content = this.ConstructContent(requestInfo), }; // Do this after setting the content, as doing so may set headers which we want to remove / override this.ApplyHeaders(requestInfo, message); // We're always going to want the content - we're a REST requesting library, and if there's a response we're always // going to parse it out before returning. If we use HttpCompletionOptions.ResponseContentRead, then our // CancellationToken will abort either the initial fetch *or* the read phases, which is what we want. var response = await this.httpClient.SendAsync(message, HttpCompletionOption.ResponseContentRead, requestInfo.CancellationToken).ConfigureAwait(false); if (!response.IsSuccessStatusCode && !requestInfo.AllowAnyStatusCode) { throw await ApiException.CreateAsync(response).ConfigureAwait(false); } return(response); }