Skip to content

Commit 9680456

Browse files
committed
feat!: Improve error handling when signing with the IAM service
BREAKING CHANGE: The ComputeCredential and ImpersonatedCredential SignBlobAsync methods will throw a GoogleApiException instead of a HttpRequestExtension. The GoogleApiException makes the HttpResponseMessage content available, which usually includes details about the error.
1 parent efd2b00 commit 9680456

File tree

3 files changed

+21
-6
lines changed

3 files changed

+21
-6
lines changed

Src/Support/Google.Apis.Auth.Tests/OAuth2/ImpersonatedCredentialTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ public async Task SignBlobAsync()
206206
public async Task SignBlobAsync_Failure()
207207
{
208208
var credential = CreateImpersonatedCredentialWithErrorResponse();
209-
var ex = await Assert.ThrowsAsync<HttpRequestException>(() => credential.SignBlobAsync(Encoding.ASCII.GetBytes("toSign")));
210-
Assert.Equal("Response status code does not indicate success: 404 (Not Found).", ex.Message);
209+
var ex = await Assert.ThrowsAsync<GoogleApiException>(() => credential.SignBlobAsync(Encoding.ASCII.GetBytes("toSign")));
210+
Assert.Equal(HttpStatusCode.NotFound, ex.HttpStatusCode);
211211
}
212212

213213
[Fact]

Src/Support/Google.Apis.Auth/OAuth2/Requests/RequestExtensions.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ limitations under the License.
1818
using Google.Apis.Json;
1919
using Google.Apis.Logging;
2020
using Google.Apis.Requests.Parameters;
21+
using Google.Apis.Responses;
2122
using Google.Apis.Util;
23+
using System;
2224
using System.Net.Http;
2325
using System.Net.Http.Headers;
2426
using System.Text;
@@ -51,7 +53,16 @@ internal static async Task<TResponse> PostJsonAsync<TResponse>(
5153
this object request, HttpClient httpClient, string url, CancellationToken cancellationToken)
5254
{
5355
var response = await request.PostJsonAsync(httpClient, url, cancellationToken).ConfigureAwait(false);
54-
response.EnsureSuccessStatusCode();
56+
if (!response.IsSuccessStatusCode)
57+
{
58+
var serviceHost = new Uri(url).Host;
59+
var error = await response.DeserializeErrorAsync(serviceHost, NewtonsoftJsonSerializer.Instance).ConfigureAwait(false);
60+
throw new GoogleApiException(serviceHost)
61+
{
62+
Error = error,
63+
HttpStatusCode = response.StatusCode
64+
};
65+
}
5566
return await NewtonsoftJsonSerializer.Instance.DeserializeAsync<TResponse>(
5667
await response.Content.ReadAsStreamAsync().ConfigureAwait(false), cancellationToken).ConfigureAwait(false);
5768
}

Src/Support/Google.Apis/Responses/HttpResponseMessageExtensions.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,11 @@
2020

2121
namespace Google.Apis.Responses
2222
{
23-
internal static class HttpResponseMessageExtensions
23+
/// <summary>
24+
/// Extension for <see cref="HttpResponseMessage"/> to help with parasing errors as returned
25+
/// by some Google services.
26+
/// </summary>
27+
public static class HttpResponseMessageExtensions
2428
{
2529
/// <summary>
2630
/// Attempts to deserialize a <see cref="RequestError"/> from the <paramref name="response"/>.
@@ -34,9 +38,9 @@ internal static class HttpResponseMessageExtensions
3438
/// </list>
3539
/// Any exception thrown while reading the <paramref name="response"/> <see cref="HttpResponseMessage.Content"/>
3640
/// will be bubbled up.
37-
/// Otherwie this method will returned the deserialized <see cref="RequestError"/>.
41+
/// Otherwie this method will return the deserialized <see cref="RequestError"/>.
3842
/// </remarks>
39-
internal static async Task<RequestError> DeserializeErrorAsync(this HttpResponseMessage response, string name, ISerializer serializer)
43+
public static async Task<RequestError> DeserializeErrorAsync(this HttpResponseMessage response, string name, ISerializer serializer)
4044
{
4145
if (response?.Content is null)
4246
{

0 commit comments

Comments
 (0)