Skip to content

Commit ccb92ed

Browse files
urbanoxBurgyn
authored andcommitted
HttpClient extension, pipeline behaviour config (#51)
* HttpClient extension, pipeline behaviour config * HttpClientFactoryExtension and unit test * Catch simplified
1 parent ca7b61a commit ccb92ed

File tree

5 files changed

+100
-8
lines changed

5 files changed

+100
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using Microsoft.AspNetCore.Http;
2+
using System.Linq;
3+
using System.Net.Http;
4+
using System.Net.Http.Headers;
5+
6+
namespace Kros.AspNetCore.Net
7+
{
8+
/// <summary>
9+
/// Extensions for HttpClientFactory.
10+
/// </summary>
11+
public static class HttpClientFactoryExtensions
12+
{
13+
/// <summary>
14+
/// Creates HttpClient with authorization header from <paramref name="httpContextAccessor"/>.
15+
/// </summary>
16+
public static HttpClient CreateClientWithAuthorization(this IHttpClientFactory httpClientFactory, IHttpContextAccessor httpContextAccessor)
17+
{
18+
HttpClient client = httpClientFactory.CreateClient();
19+
try
20+
{
21+
string authHeader = httpContextAccessor.HttpContext.Request.Headers["Authorization"].FirstOrDefault();
22+
if (authHeader != null)
23+
{
24+
AuthenticationHeaderValue.TryParse(authHeader, out AuthenticationHeaderValue newVal);
25+
client.DefaultRequestHeaders.Authorization = newVal;
26+
}
27+
}
28+
catch
29+
{
30+
client.Dispose();
31+
throw;
32+
}
33+
34+
return client;
35+
}
36+
}
37+
}

src/Kros.AspNetCore/Kros.AspNetCore.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<TargetFramework>netcoreapp2.2</TargetFramework>
5-
<Version>1.4.0</Version>
5+
<Version>1.5.0</Version>
66
<Authors>KROS a.s.</Authors>
77
<Description>General utilities and helpers for building ASP.NET Core WEB API</Description>
88
<PackageProjectUrl>https://github.com/Kros-sk/Kros.AspNetCore/tree/master/src/Kros.AspNetCore</PackageProjectUrl>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.Reflection;
2+
3+
namespace Kros.MediatR.Extensions
4+
{
5+
/// <summary>
6+
/// Config for pipeline behaviours.
7+
/// </summary>
8+
public class PipelineBehaviorsConfig
9+
{
10+
/// <summary>
11+
/// Assembly with pipeline behaviours.
12+
/// </summary>
13+
public Assembly PipelineBehaviorsAssembly { get; set; }
14+
15+
/// <summary>
16+
/// Assembly with requests.
17+
/// </summary>
18+
public Assembly RequestsAssembly { get; set; }
19+
}
20+
}

src/Kros.MediatR.Extensions/ServiceCollectionExtensions.cs

+12-7
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,20 @@ public static class ServiceCollectionExtensions
2020
/// </summary>
2121
/// <typeparam name="TRequest">Request type.</typeparam>
2222
/// <param name="services">Service container.</param>
23+
/// <param name="configAction">Pipeline behaviors config.</param>
2324
/// <exception cref="InvalidOperationException">When number of implementation
2425
/// <typeparamref name="TRequest"/> and response are different.</exception>
25-
public static IServiceCollection AddPipelineBehaviorsForRequest<TRequest>(this IServiceCollection services)
26+
public static IServiceCollection AddPipelineBehaviorsForRequest<TRequest>(this IServiceCollection services, Action<PipelineBehaviorsConfig> configAction = null)
2627
{
28+
var config = new PipelineBehaviorsConfig();
29+
configAction?.Invoke(config);
30+
2731
Type requestType = typeof(TRequest);
2832
Type pipeLineType = typeof(IPipelineBehavior<,>);
2933
string requestInterfaceName = typeof(IRequest<>).Name;
3034

31-
IList<Type> requests = GetTypes(requestType);
32-
IEnumerable<Type> pipelineBehaviors = GetPipelineBehaviors(requestType, pipeLineType);
35+
IList<Type> requests = GetTypes(requestType, config.RequestsAssembly);
36+
IEnumerable<Type> pipelineBehaviors = GetPipelineBehaviors(requestType, pipeLineType, config.PipelineBehaviorsAssembly);
3337

3438
foreach (Type behavior in pipelineBehaviors)
3539
{
@@ -59,14 +63,15 @@ public static IServiceCollection AddPipelineBehaviorsForRequest<TRequest>(this I
5963
return services;
6064
}
6165

62-
private static IEnumerable<Type> GetPipelineBehaviors(Type requestType, Type pipeLineType)
63-
=> Assembly.GetAssembly(requestType).GetTypes()
66+
private static IEnumerable<Type> GetPipelineBehaviors(Type requestType, Type pipeLineType, Assembly behavioursAssembly)
67+
=> (behavioursAssembly ?? Assembly.GetAssembly(requestType))
68+
.GetTypes()
6469
.Where(t
6570
=> t.GetInterface(pipeLineType.Name) != null
6671
&& t.GetGenericArguments()[0].GetInterface(requestType.Name) != null);
6772

68-
private static IList<Type> GetTypes(Type type)
69-
=> Assembly.GetAssembly(type)
73+
private static IList<Type> GetTypes(Type type, Assembly assembly)
74+
=> (assembly ?? Assembly.GetAssembly(type))
7075
.GetTypes()
7176
.Where(t => !t.IsInterface && !t.IsAbstract & type.IsAssignableFrom(t))
7277
.ToList();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using FluentAssertions;
2+
using Kros.AspNetCore.Net;
3+
using Microsoft.AspNetCore.Http;
4+
using NSubstitute;
5+
using System.Net.Http;
6+
using Xunit;
7+
8+
namespace Kros.AspNetCore.Tests.Extensions
9+
{
10+
public class HttpClientFactoryExtensionsShould
11+
{
12+
[Fact]
13+
public void CopyAuthorizationHeader()
14+
{
15+
var httpClient = new HttpClient();
16+
IHttpClientFactory httpClientFactory = Substitute.For<IHttpClientFactory>();
17+
httpClientFactory.CreateClient().Returns(httpClient);
18+
19+
var httpContext = new DefaultHttpContext();
20+
httpContext.Request.Headers["Authorization"] = "Bearer sfasdfasdf414weqr";
21+
IHttpContextAccessor httpContextAccessor = Substitute.For<IHttpContextAccessor>();
22+
httpContextAccessor.HttpContext.Returns(httpContext);
23+
24+
using (HttpClient clientAuth = httpClientFactory.CreateClientWithAuthorization(httpContextAccessor))
25+
{
26+
clientAuth.DefaultRequestHeaders.Authorization.Should().Equals(httpContext.Request.Headers["Authorization"]);
27+
}
28+
}
29+
}
30+
}

0 commit comments

Comments
 (0)