forked from Azure/azure-sdk-for-net
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathStorageRequestFailedException.cs
159 lines (145 loc) · 6.22 KB
/
StorageRequestFailedException.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for
// license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Core.Pipeline;
namespace Azure.Storage
{
/// <summary>
/// Provide helpful information about errors calling Azure Storage endpoints.
/// </summary>
#pragma warning disable CA1032 // Implement standard exception constructors
public partial class StorageRequestFailedException : RequestFailedException
#pragma warning restore CA1032 // Implement standard exception constructors
{
/// <summary>
/// Well known error codes for common failure conditions
/// </summary>
public string ErrorCode { get; private set; }
/// <summary>
/// Additional information helpful in debugging errors.
/// </summary>
public IDictionary<string, string> AdditionalInformation { get; private set; } = new Dictionary<string, string>();
/// <summary>
/// Gets the x-ms-request-id header that uniquely identifies the
/// request that was made and can be used for troubleshooting.
/// </summary>
public string RequestId { get; private set; }
/// <summary>
/// Create a new StorageRequestFailedException.
/// </summary>
/// <param name="response">Response of the failed request.</param>
/// <param name="message">Summary of the failure.</param>
public StorageRequestFailedException(Response response, string message = null)
: this(response, message ?? response?.ReasonPhrase, null)
{
}
/// <summary>
/// Create a new StorageRequestFailedException.
/// </summary>
/// <param name="response">Response of the failed request.</param>
/// <param name="message">Summary of the failure.</param>
/// <param name="innerException">Inner exception.</param>
public StorageRequestFailedException(Response response, string message, Exception innerException)
: this(response, message ?? response?.ReasonPhrase, innerException, null)
{
}
/// <summary>
/// Create a new StorageRequestFailedException.
/// </summary>
/// <param name="response">Response of the failed request.</param>
/// <param name="message">Summary of the failure.</param>
/// <param name="innerException">Inner exception.</param>
/// <param name="errorCode">Optional error code of the failure.</param>
/// <param name="additionalInfo">Optional additional info about the failure.</param>
internal StorageRequestFailedException(
Response response,
string message,
Exception innerException,
string errorCode,
IDictionary<string, string> additionalInfo = null)
: base(
response?.Status ?? throw Errors.ArgumentNull(nameof(response)),
CreateMessage(response, message ?? response?.ReasonPhrase, errorCode, additionalInfo),
innerException)
{
// Get the error code, if it wasn't provided
if (string.IsNullOrEmpty(errorCode))
{
response.Headers.TryGetValue(Constants.HeaderNames.ErrorCode, out errorCode);
}
ErrorCode = errorCode;
if (additionalInfo != null)
{
AdditionalInformation = additionalInfo;
}
// Include the RequestId
RequestId = response.Headers.TryGetValue(Constants.HeaderNames.RequestId, out var value) ? value : null;
}
/// <summary>
/// Create the exception's Message.
/// </summary>
/// <param name="message">The default message.</param>
/// <param name="response">The error response.</param>
/// <param name="errorCode">An optional error code.</param>
/// <param name="additionalInfo">Optional additional information.</param>
/// <returns>The exception's Message.</returns>
private static string CreateMessage(
Response response,
string message,
string errorCode,
IDictionary<string, string> additionalInfo)
{
// Start with the message, status, and reason
StringBuilder messageBuilder = new StringBuilder()
.AppendLine(message)
.Append("Status: ")
.Append(response.Status.ToString(CultureInfo.InvariantCulture))
.Append(" (")
.Append(response.ReasonPhrase)
.AppendLine(")");
// Make the Storage ErrorCode especially prominent
if (!string.IsNullOrEmpty(errorCode) ||
response.Headers.TryGetValue(Constants.HeaderNames.ErrorCode, out errorCode))
{
messageBuilder
.AppendLine()
.Append("ErrorCode: ")
.AppendLine(errorCode);
}
// A Storage error's Content is (currently) always the ErrorCode and
// AdditionalInfo, so we skip the specific Content section
if (additionalInfo != null && additionalInfo.Count > 0)
{
messageBuilder
.AppendLine()
.AppendLine("Additional Information:");
foreach (KeyValuePair<string, string> info in additionalInfo)
{
messageBuilder
.Append(info.Key)
.Append(": ")
.AppendLine(info.Value);
}
}
// Include the response headers
messageBuilder
.AppendLine()
.AppendLine("Headers:");
foreach (Core.Http.HttpHeader responseHeader in response.Headers)
{
messageBuilder
.Append(responseHeader.Name)
.Append(": ")
.AppendLine(responseHeader.Value);
}
return messageBuilder.ToString();
}
}
}