Skip to content

Commit

Permalink
Support for custom HTTP status code exception handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesRandall committed May 31, 2019
1 parent 9fbe97c commit 72849bd
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<AssemblyVersion>9.0.1.0</AssemblyVersion>
<FileVersion>9.0.1.0</FileVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageVersion>9.1.1</PackageVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
using System;
using System.Net;
using System.Net.Http;
using AzureFromTheTrenches.Commanding.Abstractions;
using AzureFromTheTrenches.Commanding.Http.Implementation;

namespace AzureFromTheTrenches.Commanding.Http
{
/// <summary>
/// A delegate used for custom exception raising when HTTP calls fail
/// </summary>
/// <param name="statusCode">The (non-success) HTTP status code</param>
/// <param name="requestUri">The URI that was called</param>
/// <param name="command">The command that triggered the error</param>
public delegate Exception HttpDispatchErrorHandler(HttpStatusCode statusCode, Uri requestUri, ICommand command);

/// <summary>
/// Creates HTTP command dispatcher functions
/// </summary>
Expand All @@ -28,13 +37,14 @@ public static class HttpCommandDispatcherFactory
HttpMethod httpMethod = null,
Func<string> authenticationHeaderContent = null,
IHttpCommandSerializer serializer = null,
IUriCommandQueryBuilder uriCommandQueryBuilder = null)
IUriCommandQueryBuilder uriCommandQueryBuilder = null,
HttpDispatchErrorHandler httpDispatchErrorHandler = null)
{
return () =>
new HttpCommandDispatcherFactoryImpl(
serializer ?? new JsonCommandSerializer(),
uriCommandQueryBuilder ?? new UriCommandQueryBuilder(),
HttpClientProvider).Create(uri, httpMethod, authenticationHeaderContent);
HttpClientProvider).Create(uri, httpMethod, authenticationHeaderContent, httpDispatchErrorHandler);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ public static class ICommandRegistryExtensions
HttpMethod httpMethod = null,
Func<string> authenticationHeaderContent = null,
IHttpCommandSerializer httpCommandSerializer = null,
IUriCommandQueryBuilder uriCommandQueryBuilder = null) where TCommand : ICommand<TResult>
IUriCommandQueryBuilder uriCommandQueryBuilder = null,
HttpDispatchErrorHandler httpDispatchErrorHandler = null) where TCommand : ICommand<TResult>
{
registry.Register<TCommand, TResult>(() => new HttpCommandDispatcher(new HttpCommandExecuter(
uri,
httpMethod, authenticationHeaderContent, httpCommandSerializer ?? new JsonCommandSerializer(),
uriCommandQueryBuilder ?? new UriCommandQueryBuilder(),
HttpCommandingDependencies.HttpClientProvider)));
HttpCommandingDependencies.HttpClientProvider,
httpDispatchErrorHandler)));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ namespace AzureFromTheTrenches.Commanding.Http
{
public interface IHttpCommandDispatcherFactory
{
ICommandDispatcher Create(Uri uri, HttpMethod httpMethod = null, Func<string> authenticationHeaderContent = null);
ICommandDispatcher Create(Uri uri,
HttpMethod httpMethod = null,
Func<string> authenticationHeaderContent = null,
HttpDispatchErrorHandler httpDispatchErrorHandler = null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@ internal class HttpCommandDispatcherFactoryImpl : IHttpCommandDispatcherFactory
_httpClientProvider = httpClientProvider;
}

public ICommandDispatcher Create(Uri uri, HttpMethod httpMethod = null, Func<string> authenticationHeaderContent = null)
public ICommandDispatcher Create(Uri uri,
HttpMethod httpMethod = null,
Func<string> authenticationHeaderContent = null,
HttpDispatchErrorHandler httpDispatchErrorHandler = null)
{
return new HttpCommandDispatcher(new HttpCommandExecuter(
uri,
httpMethod,
authenticationHeaderContent,
_httpCommandSerializer,
_uriCommandQueryBuilder,
_httpClientProvider));
_httpClientProvider,
httpDispatchErrorHandler));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,23 @@ internal class HttpCommandExecuter : ICommandExecuter
private readonly IHttpCommandSerializer _serializer;
private readonly IUriCommandQueryBuilder _uriCommandQueryBuilder;
private readonly IHttpClientProvider _httpClientProvider;
private readonly HttpDispatchErrorHandler _httpDispatchErrorHandler;

public HttpCommandExecuter(
Uri uri,
public HttpCommandExecuter(Uri uri,
HttpMethod httpMethod,
Func<string> authenticationHeaderContent,
IHttpCommandSerializer serializer,
IUriCommandQueryBuilder uriCommandQueryBuilder,
IHttpClientProvider httpClientProvider)
IHttpClientProvider httpClientProvider,
HttpDispatchErrorHandler httpDispatchErrorHandler)
{
_uri = uri;
_httpMethod = httpMethod ?? HttpMethod.Post;
_authenticationHeaderContent = authenticationHeaderContent;
_serializer = serializer;
_uriCommandQueryBuilder = uriCommandQueryBuilder;
_httpClientProvider = httpClientProvider;
_httpDispatchErrorHandler = httpDispatchErrorHandler;
}

public async Task<TResult> ExecuteAsync<TResult>(ICommand<TResult> command, CancellationToken cancellationToken)
Expand Down Expand Up @@ -65,7 +67,22 @@ public async Task<TResult> ExecuteAsync<TResult>(ICommand<TResult> command, Canc
}

HttpResponseMessage responseMessage = await _httpClientProvider.Client.SendAsync(requestMessage, cancellationToken);
responseMessage.EnsureSuccessStatusCode();
if (!responseMessage.IsSuccessStatusCode)
{
if (_httpDispatchErrorHandler != null)
{
Exception exception = _httpDispatchErrorHandler.Invoke(responseMessage.StatusCode, requestMessage.RequestUri, command);
if (exception != null)
{
throw exception;
}
}

// if we don't throw an exception from the custom handler then have the build in HTTP error handling
// kick in
responseMessage.EnsureSuccessStatusCode();
}

string result = await responseMessage.Content.ReadAsStringAsync();
return _serializer.Deserialize<TResult>(result);
}
Expand Down

0 comments on commit 72849bd

Please sign in to comment.