From cad13c74531ef377c5d1e41757ffe88a943a8974 Mon Sep 17 00:00:00 2001 From: Jake Willey Date: Fri, 28 Feb 2020 05:52:05 -0800 Subject: [PATCH] Fixed DocumentServiceResponse handling --- .../src/Handler/ResponseMessage.cs | 2 +- .../CosmosExceptionFactory.cs | 37 +++++++++- Microsoft.Azure.Cosmos/src/Util/Extensions.cs | 68 +++++++++++++------ 3 files changed, 83 insertions(+), 24 deletions(-) diff --git a/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs b/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs index 6bfa25b52f..e8985efc23 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/ResponseMessage.cs @@ -135,7 +135,7 @@ public virtual Stream Content /// /// Asserts if the current is a success. /// - public virtual bool IsSuccessStatusCode => ((int)this.StatusCode >= 200) && ((int)this.StatusCode <= 299); + public virtual bool IsSuccessStatusCode => this.StatusCode.IsSuccess(); /// /// Checks if the current has a successful status code, otherwise, throws. diff --git a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosExceptionFactory.cs b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosExceptionFactory.cs index 0f39cfe073..d83ae36ae0 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosExceptionFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/CosmosExceptions/CosmosExceptionFactory.cs @@ -5,7 +5,6 @@ namespace Microsoft.Azure.Cosmos.Resource.CosmosExceptions { using System; - using System.Diagnostics; using System.IO; using System.Net; using Microsoft.Azure.Documents; @@ -113,6 +112,42 @@ internal static CosmosException Create( responseMessage.CosmosException?.InnerException); } + internal static CosmosException Create( + DocumentServiceResponse documentServiceResponse, + Headers responseHeaders, + RequestMessage requestMessage) + { + if (documentServiceResponse == null) + { + throw new ArgumentNullException(nameof(documentServiceResponse)); + } + + if (requestMessage == null) + { + throw new ArgumentNullException(nameof(requestMessage)); + } + + if (responseHeaders == null) + { + responseHeaders = documentServiceResponse.Headers.ToCosmosHeaders(); + } + + (Error error, string errorMessage) = CosmosExceptionFactory.GetErrorFromStream(documentServiceResponse.ResponseBody); + + return CosmosExceptionFactory.Create( + statusCode: documentServiceResponse.StatusCode, + subStatusCode: (int)responseHeaders.SubStatusCode, + message: errorMessage, + stackTrace: null, + activityId: responseHeaders.ActivityId, + requestCharge: responseHeaders.RequestCharge, + retryAfter: responseHeaders.RetryAfter, + headers: responseHeaders, + diagnosticsContext: requestMessage.DiagnosticsContext, + error: error, + innerException: null); + } + internal static CosmosException Create( StoreResponse storeResponse, RequestMessage requestMessage) diff --git a/Microsoft.Azure.Cosmos/src/Util/Extensions.cs b/Microsoft.Azure.Cosmos/src/Util/Extensions.cs index d45d34c2ba..819148626b 100644 --- a/Microsoft.Azure.Cosmos/src/Util/Extensions.cs +++ b/Microsoft.Azure.Cosmos/src/Util/Extensions.cs @@ -15,43 +15,56 @@ namespace Microsoft.Azure.Cosmos using Microsoft.Azure.Cosmos.Diagnostics; using Microsoft.Azure.Cosmos.Resource.CosmosExceptions; using Microsoft.Azure.Documents; + using Microsoft.Azure.Documents.Collections; internal static class Extensions { private static readonly char[] NewLineCharacters = new[] { '\r', '\n' }; + internal static bool IsSuccess(this HttpStatusCode httpStatusCode) + { + return ((int)httpStatusCode >= 200) && ((int)httpStatusCode <= 299); + } + internal static ResponseMessage ToCosmosResponseMessage(this DocumentServiceResponse documentServiceResponse, RequestMessage requestMessage) { Debug.Assert(requestMessage != null, nameof(requestMessage)); - ResponseMessage responseMessage = new ResponseMessage(documentServiceResponse.StatusCode, requestMessage); - if (documentServiceResponse.ResponseBody != null) - { - responseMessage.Content = documentServiceResponse.ResponseBody; - } - - if (documentServiceResponse.Headers != null) - { - foreach (string key in documentServiceResponse.Headers) - { - responseMessage.Headers.Add(key, documentServiceResponse.Headers[key]); - } - } - + Headers headers = documentServiceResponse.Headers.ToCosmosHeaders(); CosmosClientSideRequestStatistics cosmosClientSideRequestStatistics = documentServiceResponse.RequestStats as CosmosClientSideRequestStatistics; - PointOperationStatistics pointOperationStatistics = new PointOperationStatistics( - activityId: responseMessage.Headers.ActivityId, + requestMessage.DiagnosticsContext.AddDiagnosticsInternal(new PointOperationStatistics( + activityId: headers.ActivityId, statusCode: documentServiceResponse.StatusCode, subStatusCode: documentServiceResponse.SubStatusCode, - requestCharge: responseMessage.Headers.RequestCharge, - errorMessage: responseMessage.ErrorMessage, + requestCharge: headers.RequestCharge, + errorMessage: null, method: requestMessage?.Method, requestUri: requestMessage?.RequestUri, requestSessionToken: requestMessage?.Headers?.Session, - responseSessionToken: responseMessage.Headers.Session, - clientSideRequestStatistics: cosmosClientSideRequestStatistics); + responseSessionToken: headers.Session, + clientSideRequestStatistics: cosmosClientSideRequestStatistics)); + + // If it's considered a failure create the corresponding CosmosException + if (!documentServiceResponse.StatusCode.IsSuccess()) + { + CosmosException cosmosException = CosmosExceptionFactory.Create( + documentServiceResponse, + headers, + requestMessage); + + return cosmosException.ToCosmosResponseMessage(requestMessage); + } + + ResponseMessage responseMessage = new ResponseMessage( + statusCode: documentServiceResponse.StatusCode, + requestMessage: requestMessage, + headers: headers, + cosmosException: null, + diagnostics: requestMessage.DiagnosticsContext) + { + Content = documentServiceResponse.ResponseBody + }; - requestMessage.DiagnosticsContext.AddDiagnosticsInternal(pointOperationStatistics); return responseMessage; } @@ -102,7 +115,7 @@ internal static ResponseMessage ToCosmosResponseMessage(this DocumentClientExcep internal static ResponseMessage ToCosmosResponseMessage(this StoreResponse storeResponse, RequestMessage requestMessage) { // If it's considered a failure create the corresponding CosmosException - if (((int)storeResponse.StatusCode >= 200) && ((int)storeResponse.StatusCode <= 299)) + if (!storeResponse.StatusCode.IsSuccess()) { CosmosException cosmosException = CosmosExceptionFactory.Create( storeResponse, @@ -132,6 +145,17 @@ internal static Headers ToCosmosHeaders(this StoreResponse storeResponse) return headers; } + internal static Headers ToCosmosHeaders(this INameValueCollection nameValueCollection) + { + Headers headers = new Headers(); + foreach (string key in nameValueCollection) + { + headers.Add(key, nameValueCollection[key]); + } + + return headers; + } + internal static void TraceException(Exception exception) { AggregateException aggregateException = exception as AggregateException;