public void BadResponse <TResponse>(ref TResponse response, IApiCallDetails callDetails, RequestData data, TransportException exception ) where TResponse : class, ITransportResponse, 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 : _memoryStreamFactory.Create(callDetails.ResponseBodyInBytes); var m = callDetails?.ResponseMimeType ?? RequestData.MimeType; response = ResponseBuilder.ToResponse <TResponse>(data, exception, callDetails?.HttpStatusCode, null, s, m); } response.ApiCall.AuditTrail = AuditTrail; }
/// <inheritdoc cref="IConnection.Request{TResponse}"/>> public virtual TResponse Request <TResponse>(RequestData requestData) where TResponse : class, ITransportResponse, 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); }