Permalink
Browse files

Error handling

  • Loading branch information...
1 parent fc2cb91 commit 27ecb4ba5707b1f8b0502893c554b939fbf35aae Aliaksei Baturytski committed Apr 18, 2012
View
66 ...er/Microsoft.WindowsAzure.ServiceLayer.UnitTests.MsTest/HttpTests/HttpErrorHelperTests.cs
@@ -1,66 +0,0 @@
-//
-// Copyright 2012 Microsoft Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
-using Microsoft.WindowsAzure.ServiceLayer.Http;
-
-namespace Microsoft.WindowsAzure.ServiceLayer.UnitTests.MsTest.HttpTests
-{
- /// <summary>
- /// Tests for encoding/decoding HRESULTs.
- /// </summary>
- [TestClass]
- public class HttpErrorHelperTests
- {
- /// <summary>
- /// Tests passing invalid error sources to the GetComErrorCode method.
- /// </summary>
- [TestMethod]
- public void InvalidErrorSource()
- {
- Assert.ThrowsException<ArgumentOutOfRangeException>(() => HttpErrorHelper.CreateComErrorCode((WindowsAzureErrorSource)(-1), 200));
- Assert.ThrowsException<ArgumentOutOfRangeException>(() => HttpErrorHelper.CreateComErrorCode((WindowsAzureErrorSource)2, 200));
- }
-
- /// <summary>
- /// Tests passing invalid HTTP status to the GetComErrorCode method.
- /// </summary>
- [TestMethod]
- public void InvalidHttpStatus()
- {
- Assert.ThrowsException<ArgumentOutOfRangeException>(() => HttpErrorHelper.CreateComErrorCode(WindowsAzureErrorSource.ServiceBus, -1));
- }
-
- /// <summary>
- /// Tests passing invalid HRESULTs to the TranslateComErrorCode method.
- /// </summary>
- [TestMethod]
- public void InvalidComErrorCode()
- {
- int validCode = HttpErrorHelper.CreateComErrorCode(WindowsAzureErrorSource.ServiceBus, 400);
- WindowsAzureErrorSource source;
- int code;
-
- Assert.ThrowsException<ArgumentException>(() => HttpErrorHelper.ParseComErrorCode(validCode & 0x7FFFFFFF, out source, out code)); // Invalid severity.
- Assert.ThrowsException<ArgumentException>(() => HttpErrorHelper.ParseComErrorCode(validCode | 0x0000F000, out source, out code)); // Invalid error source.
- Assert.ThrowsException<ArgumentException>(() => HttpErrorHelper.ParseComErrorCode(validCode | 0x00000FFF, out source, out code)); // Invalid error code.
- }
- }
-}
View
1 ...ServiceLayer.UnitTests.MsTest/Microsoft.WindowsAzure.ServiceLayer.UnitTests.MsTest.csproj
@@ -111,7 +111,6 @@
<ItemGroup>
<Compile Include="Configuration.cs" />
<Compile Include="HttpTests\ContentTests.cs" />
- <Compile Include="HttpTests\HttpErrorHelperTests.cs" />
<Compile Include="HttpTests\PipelineTests.cs" />
<Compile Include="HttpTests\TestHttpHandler.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
View
4 microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Constants.cs
@@ -26,6 +26,10 @@ namespace Microsoft.WindowsAzure.ServiceLayer
/// </summary>
internal static class Constants
{
+ private const int ComErrorMask = unchecked((int)0x80040000); // Mask for all COM error codes
+ internal const int WrapErrorMask = ComErrorMask; // Mask for WRAP exceptions
+ internal const int HttpErrorMask = ComErrorMask | 0x1000; // Mask for HTTP exceptions
+
internal const string ServiceBusServiceUri = "https://{0}.servicebus.windows.net/";
internal const string ServiceBusAuthenticationUri = "https://{0}-sb.accesscontrol.windows.net/wrapv0.9/";
internal const string ServiceBusScopeUri = "http://{0}.servicebus.windows.net/";
View
112 microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/HttpErrorHelper.cs
@@ -1,112 +0,0 @@
-//
-// Copyright 2012 Microsoft Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Microsoft.WindowsAzure.ServiceLayer.Http
-{
- /// <summary>
- /// Helper methods for working with HTTP error codes.
- /// </summary>
- /// <remarks>HRESULT structure for HTTP errors:
- /// Severity: SEVERITY_ERROR
- /// Facility: FACILITY_ITF
- /// 6 bits for error source
- /// 10 bits for the HTTP status code.
- ///
- /// More info on HRESULT: http://msdn.microsoft.com/en-us/library/bb446131.aspx
- /// </remarks>
- public static class HttpErrorHelper
- {
- private const uint ComErrorMask = 0x80040000; // severity: error; facility: intf.
- private const uint ErrorSourceMask = 0x0000FC00; // 6 bits.
- private const int ErrorSourceOffset = 10; // Offset of the error source (# of bits)
- private const uint HttpStatusMask = 0x000003FF; // Last 10 bits.
-
- /// <summary>
- /// Creates HRESULT for the given HTTP error.
- /// </summary>
- /// <param name="source">The source of error.</param>
- /// <param name="httpStatusCode">HTTP status code.</param>
- /// <returns>HRESULT with embedded source and status code.</returns>
- public static int CreateComErrorCode(WindowsAzureErrorSource source, int httpStatusCode)
- {
- Validator.ArgumentIsValidEnumValue<WindowsAzureErrorSource>("source", source);
- Validator.ArgumentIsValidEnumValue<System.Net.HttpStatusCode>("httpStatusCode", httpStatusCode);
-
- // 10 bits should be enough for the error code!
- Debug.Assert((httpStatusCode & ErrorSourceMask) == 0);
- uint code = ComErrorMask;
- code |= ((uint)source) << ErrorSourceOffset;
- code |= (uint)httpStatusCode;
- return (int)code;
- }
-
- /// <summary>
- /// Extracts source and HTTP status code from the given HRESULT.
- /// </summary>
- /// <param name="comErrorCode">COM error code (HRESULT).</param>
- /// <param name="source">Error source.</param>
- /// <param name="httpStatusCode">HTTP status code.</param>
- public static void ParseComErrorCode(int comErrorCode, out WindowsAzureErrorSource source, out int httpStatusCode)
- {
- if (!TryParseComErrorCode(comErrorCode, out source, out httpStatusCode))
- {
- string message = string.Format(CultureInfo.CurrentUICulture, Resources.ErrorArgumentInvalidComError, "comErrorCode");
- throw new ArgumentException(message);
- }
- }
-
- /// <summary>
- /// Attempts to extract source and HTTP status code from the given HRESULT.
- /// </summary>
- /// <param name="comErrorCode">COM error code (HRESULT).</param>
- /// <param name="source">Error source.</param>
- /// <param name="httpStatusCode">HTTP status code.</param>
- /// <returns>True if COM error code was successfully parsed.</returns>
- public static bool TryParseComErrorCode(int comErrorCode, out WindowsAzureErrorSource source, out int httpStatusCode)
- {
- source = 0;
- httpStatusCode = 0;
-
- if ((comErrorCode & ComErrorMask) != ComErrorMask)
- {
- return false;
- }
-
- WindowsAzureErrorSource tempErrorSource = (WindowsAzureErrorSource)((comErrorCode & ErrorSourceMask) >> ErrorSourceOffset);
- if (!Enum.IsDefined(typeof(WindowsAzureErrorSource), tempErrorSource))
- {
- return false;
- }
-
- int tempStatusCode = (int)((uint)comErrorCode & HttpStatusMask);
- if (!Enum.IsDefined(typeof(System.Net.HttpStatusCode), tempStatusCode))
- {
- return false;
- }
-
- source = tempErrorSource;
- httpStatusCode = tempStatusCode;
- return true;
- }
- }
-}
View
27 ...-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/WindowsAzureHttpException.cs
@@ -31,23 +31,22 @@ internal class WindowsAzureHttpException: WindowsAzureException
/// <summary>
/// Initializes the exception with data from the given HTTP response.
/// </summary>
- /// <param name="message">Error message.</param>
+ /// <param name="shortMessage">Error message.</param>
/// <param name="response">HTTP response.</param>
- internal WindowsAzureHttpException(string message, HttpResponse response)
- : this(message, WindowsAzureErrorSource.ServiceBus, response)
+ internal WindowsAzureHttpException(string shortMessage, HttpResponse response)
+ : this(shortMessage, response, CreateComErrorCode(response))
{
}
/// <summary>
/// Initializes the exception.
/// </summary>
- /// <param name="message">Short error message.</param>
- /// <param name="source">Error source.</param>
+ /// <param name="shortMessage">Short error message.</param>
/// <param name="response">HTTP response that triggered the exception.</param>
- protected WindowsAzureHttpException(string message, WindowsAzureErrorSource source, HttpResponse response)
- : base(GetHttpErrorMessage(message, response))
+ /// <param name="errorCode">Error code to be associated with the exception.</param>
+ protected WindowsAzureHttpException(string shortMessage, HttpResponse response, int errorCode)
+ : base(GetHttpErrorMessage(shortMessage, response), errorCode)
{
- HResult = HttpErrorHelper.CreateComErrorCode(source, response.StatusCode);
}
/// <summary>
@@ -56,10 +55,20 @@ protected WindowsAzureHttpException(string message, WindowsAzureErrorSource sour
/// <param name="message">Short message.</param>
/// <param name="response">HTTP response with more details.</param>
/// <returns>Error message.</returns>
- protected static string GetHttpErrorMessage(string message, HttpResponse response)
+ private static string GetHttpErrorMessage(string message, HttpResponse response)
{
string details = string.Format(CultureInfo.CurrentUICulture, Resources.HttpDetails, response.StatusCode, response.ReasonPhrase);
return string.Format(CultureInfo.CurrentUICulture, Resources.HttpErrorMessage, message, details);
}
+
+ /// <summary>
+ /// Creates a COM error code for the given HTTP response.
+ /// </summary>
+ /// <param name="response">HTTP response.</param>
+ /// <returns>COM error code.</returns>
+ private static int CreateComErrorCode(HttpResponse response)
+ {
+ return unchecked((int)(Constants.HttpErrorMask | response.StatusCode));
+ }
}
}
View
2 ...zure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/Http/WrapAuthenticationException.cs
@@ -32,7 +32,7 @@ internal class WrapAuthenticationException: WindowsAzureHttpException
/// </summary>
/// <param name="response">Response.</param>
internal WrapAuthenticationException(HttpResponse response)
- : base(Resources.ErrorWrapAuthentication, WindowsAzureErrorSource.WrapAuthentication, response)
+ : base(Resources.ErrorWrapAuthentication, response, (int)WindowsAzureErrorCode.WrapAuthenticationFailure)
{
}
}
View
3 ...rvicelayer/Microsoft.WindowsAzure.ServiceLayer/Microsoft.WindowsAzure.ServiceLayer.csproj
@@ -105,11 +105,10 @@
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
- <Compile Include="WindowsAzureErrorSource.cs" />
+ <Compile Include="WindowsAzureErrorCode.cs" />
<Compile Include="Http\HttpChannel.cs" />
<Compile Include="Http\HttpContent.cs" />
<Compile Include="Http\HttpDefaultHandler.cs" />
- <Compile Include="Http\HttpErrorHelper.cs" />
<Compile Include="Http\HttpMethod.cs" />
<Compile Include="Http\HttpRequest.cs" />
<Compile Include="Http\HttpResponse.cs" />
View
87 microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/WindowsAzureErrorCode.cs
@@ -0,0 +1,87 @@
+//
+// Copyright 2012 Microsoft Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.WindowsAzure.ServiceLayer
+{
+ /// <summary>
+ /// A collection of well-known error codes.
+ /// </summary>
+ public enum WindowsAzureErrorCode
+ {
+ // Internal HRESULT structure:
+ // Bits 31 - 16: HRESULT flags indicating an error (Severity: ERROR; facility: ITF)
+ // Bits 12 - 15: error source (HTTP, WRAP, etc)
+ // Bits 0 - 11: source-specific information, if any. Contains status code for HTTP errors.
+
+ // Generic WRAP authentication failure.
+ WrapAuthenticationFailure = Constants.WrapErrorMask,
+
+ // HTTP status exceptions
+ HttpContinue = Constants.HttpErrorMask | HttpStatusCode.Continue,
+ HttpSwitchingProtocols = Constants.HttpErrorMask | HttpStatusCode.SwitchingProtocols,
+ HttpOK = Constants.HttpErrorMask | HttpStatusCode.OK,
+ HttpCreated = Constants.HttpErrorMask | HttpStatusCode.Created,
+ HttpAccepted = Constants.HttpErrorMask | HttpStatusCode.Accepted,
+ HttpNonAuthoritativeInformation = Constants.HttpErrorMask | HttpStatusCode.NonAuthoritativeInformation,
+ HttpNoContent = Constants.HttpErrorMask | HttpStatusCode.NoContent,
+ HttpResetContent = Constants.HttpErrorMask | HttpStatusCode.ResetContent,
+ HttpPartialContent = Constants.HttpErrorMask | HttpStatusCode.PartialContent,
+ HttpMultipleChoices = Constants.HttpErrorMask | HttpStatusCode.MultipleChoices,
+ HttpAmbiguous = Constants.HttpErrorMask | HttpStatusCode.Ambiguous,
+ HttpMovedPermanently = Constants.HttpErrorMask | HttpStatusCode.MovedPermanently,
+ HttpMoved = Constants.HttpErrorMask | HttpStatusCode.Moved,
+ HttpFound = Constants.HttpErrorMask | HttpStatusCode.Found,
+ HttpRedirect = Constants.HttpErrorMask | HttpStatusCode.Redirect,
+ HttpSeeOther = Constants.HttpErrorMask | HttpStatusCode.SeeOther,
+ HttpRedirectMethod = Constants.HttpErrorMask | HttpStatusCode.RedirectMethod,
+ HttpNotModified = Constants.HttpErrorMask | HttpStatusCode.NotModified,
+ HttpUseProxy = Constants.HttpErrorMask | HttpStatusCode.UseProxy,
+ HttpUnused = Constants.HttpErrorMask | HttpStatusCode.Unused,
+ HttpRedirectKeepVerb = Constants.HttpErrorMask | HttpStatusCode.RedirectKeepVerb,
+ HttpTemporaryRedirect = Constants.HttpErrorMask | HttpStatusCode.TemporaryRedirect,
+ HttpBadRequest = Constants.HttpErrorMask | HttpStatusCode.BadRequest,
+ HttpUnauthorized = Constants.HttpErrorMask | HttpStatusCode.Unauthorized,
+ HttpPaymentRequired = Constants.HttpErrorMask | HttpStatusCode.PaymentRequired,
+ HttpForbidden = Constants.HttpErrorMask | HttpStatusCode.Forbidden,
+ HttpNotFound = Constants.HttpErrorMask | HttpStatusCode.NotFound,
+ HttpMethodNotAllowed = Constants.HttpErrorMask | HttpStatusCode.MethodNotAllowed,
+ HttpNotAcceptable = Constants.HttpErrorMask | HttpStatusCode.NotAcceptable,
+ HttpProxyAuthenticationRequired = Constants.HttpErrorMask | HttpStatusCode.ProxyAuthenticationRequired,
+ HttpRequestTimeout = Constants.HttpErrorMask | HttpStatusCode.RequestTimeout,
+ HttpConflict = Constants.HttpErrorMask | HttpStatusCode.Conflict,
+ HttpGone = Constants.HttpErrorMask | HttpStatusCode.Gone,
+ HttpLengthRequired = Constants.HttpErrorMask | HttpStatusCode.LengthRequired,
+ HttpPreconditionFailed = Constants.HttpErrorMask | HttpStatusCode.PreconditionFailed,
+ HttpRequestEntityTooLarge = Constants.HttpErrorMask | HttpStatusCode.RequestEntityTooLarge,
+ HttpRequestUriTooLong = Constants.HttpErrorMask | HttpStatusCode.RequestUriTooLong,
+ HttpUnsupportedMediaType = Constants.HttpErrorMask | HttpStatusCode.UnsupportedMediaType,
+ HttpRequestedRangeNotSatisfiable = Constants.HttpErrorMask | HttpStatusCode.RequestedRangeNotSatisfiable,
+ HttpExpectationFailed = Constants.HttpErrorMask | HttpStatusCode.ExpectationFailed,
+ HttpUpgradeRequired = Constants.HttpErrorMask | HttpStatusCode.UpgradeRequired,
+ HttpInternalServerError = Constants.HttpErrorMask | HttpStatusCode.InternalServerError,
+ HttpNotImplemented = Constants.HttpErrorMask | HttpStatusCode.NotImplemented,
+ HttpBadGateway = Constants.HttpErrorMask | HttpStatusCode.BadGateway,
+ HttpServiceUnavailable = Constants.HttpErrorMask | HttpStatusCode.ServiceUnavailable,
+ HttpGatewayTimeout = Constants.HttpErrorMask | HttpStatusCode.GatewayTimeout,
+ HttpVersionNotSupported = Constants.HttpErrorMask | HttpStatusCode.HttpVersionNotSupported,
+ }
+}
View
32 microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/WindowsAzureErrorSource.cs
@@ -1,32 +0,0 @@
-//
-// Copyright 2012 Microsoft Corporation
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Microsoft.WindowsAzure.ServiceLayer
-{
- /// <summary>
- /// Specifies source of an error.
- /// </summary>
- public enum WindowsAzureErrorSource
- {
- ServiceBus, // The error comes from the service bus call.
- WrapAuthentication, // The error comes from WRAP authentication call.
- }
-}
View
7 microsoft-azure-servicelayer/Microsoft.WindowsAzure.ServiceLayer/WindowsAzureException.cs
@@ -26,9 +26,10 @@ internal class WindowsAzureException: COMException
/// <summary>
/// Initializes the exception with the specified error message.
/// </summary>
- /// <param name="message"></param>
- internal WindowsAzureException(string message)
- : base(message)
+ /// <param name="message">Error message.</param>
+ /// <param name="errorCode">COM error code.</param>
+ internal WindowsAzureException(string message, int errorCode)
+ : base(message, errorCode)
{
}
}

0 comments on commit 27ecb4b

Please sign in to comment.