Feature/rename middleware (#637)

* #630 only set status code if response hasnt started, otherwise exception

* #623 made {RemoteIpAddress} available as placeholder so you can do x-forwarded-for

* #623 local address different on mac, windows and linux for integration test

* renamed some middlewares so they make more sense

* add downstreamroutefindermiddleware benchmark
This commit is contained in:
Tom Pallister 2018-09-25 20:25:38 +01:00 committed by GitHub
parent 4a8f4c2e03
commit dc28d49bda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 694 additions and 619 deletions

View File

@ -1,46 +1,46 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Infrastructure.Claims.Parser; using Ocelot.Infrastructure.Claims.Parser;
using Ocelot.Responses; using Ocelot.Responses;
namespace Ocelot.Claims namespace Ocelot.Claims
{ {
public class AddClaimsToRequest : IAddClaimsToRequest public class AddClaimsToRequest : IAddClaimsToRequest
{ {
private readonly IClaimsParser _claimsParser; private readonly IClaimsParser _claimsParser;
public AddClaimsToRequest(IClaimsParser claimsParser) public AddClaimsToRequest(IClaimsParser claimsParser)
{ {
_claimsParser = claimsParser; _claimsParser = claimsParser;
} }
public Response SetClaimsOnContext(List<ClaimToThing> claimsToThings, HttpContext context) public Response SetClaimsOnContext(List<ClaimToThing> claimsToThings, HttpContext context)
{ {
foreach (var config in claimsToThings) foreach (var config in claimsToThings)
{ {
var value = _claimsParser.GetValue(context.User.Claims, config.NewKey, config.Delimiter, config.Index); var value = _claimsParser.GetValue(context.User.Claims, config.NewKey, config.Delimiter, config.Index);
if (value.IsError) if (value.IsError)
{ {
return new ErrorResponse(value.Errors); return new ErrorResponse(value.Errors);
} }
var exists = context.User.Claims.FirstOrDefault(x => x.Type == config.ExistingKey); var exists = context.User.Claims.FirstOrDefault(x => x.Type == config.ExistingKey);
var identity = context.User.Identity as ClaimsIdentity; var identity = context.User.Identity as ClaimsIdentity;
if (exists != null) if (exists != null)
{ {
identity?.RemoveClaim(exists); identity?.RemoveClaim(exists);
} }
identity?.AddClaim(new System.Security.Claims.Claim(config.ExistingKey, value.Data)); identity?.AddClaim(new System.Security.Claims.Claim(config.ExistingKey, value.Data));
} }
return new OkResponse(); return new OkResponse();
} }
} }
} }

View File

@ -1,13 +1,13 @@
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Ocelot.Middleware.Pipeline; using Ocelot.Middleware.Pipeline;
namespace Ocelot.Claims.Middleware namespace Ocelot.Claims.Middleware
{ {
public static class ClaimsBuilderMiddlewareExtensions public static class ClaimsToClaimsMiddlewareExtensions
{ {
public static IOcelotPipelineBuilder UseClaimsBuilderMiddleware(this IOcelotPipelineBuilder builder) public static IOcelotPipelineBuilder UseClaimsToClaimsMiddleware(this IOcelotPipelineBuilder builder)
{ {
return builder.UseMiddleware<ClaimsBuilderMiddleware>(); return builder.UseMiddleware<ClaimsToClaimsMiddleware>();
} }
} }
} }

View File

@ -1,45 +1,45 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.DownstreamRouteFinder.Middleware; using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.Claims.Middleware namespace Ocelot.Claims.Middleware
{ {
public class ClaimsBuilderMiddleware : OcelotMiddleware public class ClaimsToClaimsMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IAddClaimsToRequest _addClaimsToRequest; private readonly IAddClaimsToRequest _addClaimsToRequest;
public ClaimsBuilderMiddleware(OcelotRequestDelegate next, public ClaimsToClaimsMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IAddClaimsToRequest addClaimsToRequest) IAddClaimsToRequest addClaimsToRequest)
:base(loggerFactory.CreateLogger<ClaimsBuilderMiddleware>()) :base(loggerFactory.CreateLogger<ClaimsToClaimsMiddleware>())
{ {
_next = next; _next = next;
_addClaimsToRequest = addClaimsToRequest; _addClaimsToRequest = addClaimsToRequest;
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
{ {
if (context.DownstreamReRoute.ClaimsToClaims.Any()) if (context.DownstreamReRoute.ClaimsToClaims.Any())
{ {
Logger.LogDebug("this route has instructions to convert claims to other claims"); Logger.LogDebug("this route has instructions to convert claims to other claims");
var result = _addClaimsToRequest.SetClaimsOnContext(context.DownstreamReRoute.ClaimsToClaims, context.HttpContext); var result = _addClaimsToRequest.SetClaimsOnContext(context.DownstreamReRoute.ClaimsToClaims, context.HttpContext);
if (result.IsError) if (result.IsError)
{ {
Logger.LogDebug("error converting claims to other claims, setting pipeline error"); Logger.LogDebug("error converting claims to other claims, setting pipeline error");
SetPipelineError(context, result.Errors); SetPipelineError(context, result.Errors);
return; return;
} }
} }
await _next.Invoke(context); await _next.Invoke(context);
} }
} }
} }

View File

@ -1,83 +1,83 @@
namespace Ocelot.Headers namespace Ocelot.Headers
{ {
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Infrastructure; using Infrastructure;
using Logging; using Logging;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Infrastructure.Claims.Parser; using Ocelot.Infrastructure.Claims.Parser;
using Ocelot.Responses; using Ocelot.Responses;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
using Ocelot.Configuration.Creator; using Ocelot.Configuration.Creator;
using Ocelot.Middleware; using Ocelot.Middleware;
using Ocelot.Request.Middleware; using Ocelot.Request.Middleware;
public class AddHeadersToRequest : IAddHeadersToRequest public class AddHeadersToRequest : IAddHeadersToRequest
{ {
private readonly IClaimsParser _claimsParser; private readonly IClaimsParser _claimsParser;
private readonly IPlaceholders _placeholders; private readonly IPlaceholders _placeholders;
private readonly IOcelotLogger _logger; private readonly IOcelotLogger _logger;
public AddHeadersToRequest(IClaimsParser claimsParser, IPlaceholders placeholders, IOcelotLoggerFactory factory) public AddHeadersToRequest(IClaimsParser claimsParser, IPlaceholders placeholders, IOcelotLoggerFactory factory)
{ {
_logger = factory.CreateLogger<AddHeadersToRequest>(); _logger = factory.CreateLogger<AddHeadersToRequest>();
_claimsParser = claimsParser; _claimsParser = claimsParser;
_placeholders = placeholders; _placeholders = placeholders;
} }
public Response SetHeadersOnDownstreamRequest(List<ClaimToThing> claimsToThings, IEnumerable<System.Security.Claims.Claim> claims, DownstreamRequest downstreamRequest) public Response SetHeadersOnDownstreamRequest(List<ClaimToThing> claimsToThings, IEnumerable<System.Security.Claims.Claim> claims, DownstreamRequest downstreamRequest)
{ {
foreach (var config in claimsToThings) foreach (var config in claimsToThings)
{ {
var value = _claimsParser.GetValue(claims, config.NewKey, config.Delimiter, config.Index); var value = _claimsParser.GetValue(claims, config.NewKey, config.Delimiter, config.Index);
if (value.IsError) if (value.IsError)
{ {
return new ErrorResponse(value.Errors); return new ErrorResponse(value.Errors);
} }
var exists = downstreamRequest.Headers.FirstOrDefault(x => x.Key == config.ExistingKey); var exists = downstreamRequest.Headers.FirstOrDefault(x => x.Key == config.ExistingKey);
if (!string.IsNullOrEmpty(exists.Key)) if (!string.IsNullOrEmpty(exists.Key))
{ {
downstreamRequest.Headers.Remove(exists.Key); downstreamRequest.Headers.Remove(exists.Key);
} }
downstreamRequest.Headers.Add(config.ExistingKey, value.Data); downstreamRequest.Headers.Add(config.ExistingKey, value.Data);
} }
return new OkResponse(); return new OkResponse();
} }
public void SetHeadersOnDownstreamRequest(IEnumerable<AddHeader> headers, HttpContext context) public void SetHeadersOnDownstreamRequest(IEnumerable<AddHeader> headers, HttpContext context)
{ {
var requestHeader = context.Request.Headers; var requestHeader = context.Request.Headers;
foreach (var header in headers) foreach (var header in headers)
{ {
if (requestHeader.ContainsKey(header.Key)) if (requestHeader.ContainsKey(header.Key))
{ {
requestHeader.Remove(header.Key); requestHeader.Remove(header.Key);
} }
if (header.Value.StartsWith("{") && header.Value.EndsWith("}")) if (header.Value.StartsWith("{") && header.Value.EndsWith("}"))
{ {
var value = _placeholders.Get(header.Value); var value = _placeholders.Get(header.Value);
if (value.IsError) if (value.IsError)
{ {
_logger.LogWarning($"Unable to add header to response {header.Key}: {header.Value}"); _logger.LogWarning($"Unable to add header to response {header.Key}: {header.Value}");
continue; continue;
} }
requestHeader.Add(header.Key, new StringValues(value.Data)); requestHeader.Add(header.Key, new StringValues(value.Data));
} }
else else
{ {
requestHeader.Add(header.Key, header.Value); requestHeader.Add(header.Key, header.Value);
} }
} }
} }
} }
} }

View File

@ -1,25 +1,25 @@
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Responses; using Ocelot.Responses;
namespace Ocelot.Headers namespace Ocelot.Headers
{ {
public class HttpContextRequestHeaderReplacer : IHttpContextRequestHeaderReplacer public class HttpContextRequestHeaderReplacer : IHttpContextRequestHeaderReplacer
{ {
public Response Replace(HttpContext context, List<HeaderFindAndReplace> fAndRs) public Response Replace(HttpContext context, List<HeaderFindAndReplace> fAndRs)
{ {
foreach (var f in fAndRs) foreach (var f in fAndRs)
{ {
if(context.Request.Headers.TryGetValue(f.Key, out var values)) if(context.Request.Headers.TryGetValue(f.Key, out var values))
{ {
var replaced = values[f.Index].Replace(f.Find, f.Replace); var replaced = values[f.Index].Replace(f.Find, f.Replace);
context.Request.Headers.Remove(f.Key); context.Request.Headers.Remove(f.Key);
context.Request.Headers.Add(f.Key, replaced); context.Request.Headers.Add(f.Key, replaced);
} }
} }
return new OkResponse(); return new OkResponse();
} }
} }
} }

View File

@ -1,47 +1,47 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Ocelot.DownstreamRouteFinder.Middleware; using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Infrastructure.RequestData; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.Headers.Middleware namespace Ocelot.Headers.Middleware
{ {
public class HttpRequestHeadersBuilderMiddleware : OcelotMiddleware public class ClaimsToHeadersMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IAddHeadersToRequest _addHeadersToRequest; private readonly IAddHeadersToRequest _addHeadersToRequest;
public HttpRequestHeadersBuilderMiddleware(OcelotRequestDelegate next, public ClaimsToHeadersMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IAddHeadersToRequest addHeadersToRequest) IAddHeadersToRequest addHeadersToRequest)
:base(loggerFactory.CreateLogger<HttpRequestHeadersBuilderMiddleware>()) :base(loggerFactory.CreateLogger<ClaimsToHeadersMiddleware>())
{ {
_next = next; _next = next;
_addHeadersToRequest = addHeadersToRequest; _addHeadersToRequest = addHeadersToRequest;
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
{ {
if (context.DownstreamReRoute.ClaimsToHeaders.Any()) if (context.DownstreamReRoute.ClaimsToHeaders.Any())
{ {
Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to headers"); Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to headers");
var response = _addHeadersToRequest.SetHeadersOnDownstreamRequest(context.DownstreamReRoute.ClaimsToHeaders, context.HttpContext.User.Claims, context.DownstreamRequest); var response = _addHeadersToRequest.SetHeadersOnDownstreamRequest(context.DownstreamReRoute.ClaimsToHeaders, context.HttpContext.User.Claims, context.DownstreamRequest);
if (response.IsError) if (response.IsError)
{ {
Logger.LogWarning("Error setting headers on context, setting pipeline error"); Logger.LogWarning("Error setting headers on context, setting pipeline error");
SetPipelineError(context, response.Errors); SetPipelineError(context, response.Errors);
return; return;
} }
Logger.LogInformation("headers have been set on context"); Logger.LogInformation("headers have been set on context");
} }
await _next.Invoke(context); await _next.Invoke(context);
} }
} }
} }

View File

@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Builder;
using Ocelot.Middleware.Pipeline;
namespace Ocelot.Headers.Middleware
{
public static class ClaimsToHeadersMiddlewareExtensions
{
public static IOcelotPipelineBuilder UseClaimsToHeadersMiddleware(this IOcelotPipelineBuilder builder)
{
return builder.UseMiddleware<ClaimsToHeadersMiddleware>();
}
}
}

View File

@ -1,13 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Ocelot.Middleware.Pipeline;
namespace Ocelot.Headers.Middleware
{
public static class HttpRequestHeadersBuilderMiddlewareExtensions
{
public static IOcelotPipelineBuilder UseHttpRequestHeadersBuilderMiddleware(this IOcelotPipelineBuilder builder)
{
return builder.UseMiddleware<HttpRequestHeadersBuilderMiddleware>();
}
}
}

View File

@ -91,7 +91,7 @@ namespace Ocelot.Middleware.Pipeline
} }
// The next thing we do is look at any claims transforms in case this is important for authorisation // The next thing we do is look at any claims transforms in case this is important for authorisation
builder.UseClaimsBuilderMiddleware(); builder.UseClaimsToClaimsMiddleware();
// Allow pre authorisation logic. The idea being people might want to run something custom before what is built in. // Allow pre authorisation logic. The idea being people might want to run something custom before what is built in.
builder.UseIfNotNull(pipelineConfiguration.PreAuthorisationMiddleware); builder.UseIfNotNull(pipelineConfiguration.PreAuthorisationMiddleware);
@ -109,14 +109,14 @@ namespace Ocelot.Middleware.Pipeline
builder.Use(pipelineConfiguration.AuthorisationMiddleware); builder.Use(pipelineConfiguration.AuthorisationMiddleware);
} }
// Now we can run any header transformation logic // Now we can run the claims to headers transformation middleware
builder.UseHttpRequestHeadersBuilderMiddleware(); builder.UseClaimsToHeadersMiddleware();
// Allow the user to implement their own query string manipulation logic // Allow the user to implement their own query string manipulation logic
builder.UseIfNotNull(pipelineConfiguration.PreQueryStringBuilderMiddleware); builder.UseIfNotNull(pipelineConfiguration.PreQueryStringBuilderMiddleware);
// Now we can run any query string transformation logic // Now we can run any claims to query string transformation middleware
builder.UseQueryStringBuilderMiddleware(); builder.UseClaimsToQueryStringMiddleware();
// Get the load balancer for this request // Get the load balancer for this request
builder.UseLoadBalancingMiddleware(); builder.UseLoadBalancingMiddleware();

View File

@ -1,45 +1,45 @@
using System.Linq; namespace Ocelot.QueryStrings.Middleware
using System.Threading.Tasks; {
using Microsoft.AspNetCore.Http; using System.Linq;
using Ocelot.DownstreamRouteFinder.Middleware; using System.Threading.Tasks;
using Ocelot.Infrastructure.RequestData; using Microsoft.AspNetCore.Http;
using Ocelot.Logging; using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Middleware; using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
namespace Ocelot.QueryStrings.Middleware using Ocelot.Middleware;
{
public class QueryStringBuilderMiddleware : OcelotMiddleware public class ClaimsToQueryStringMiddleware : OcelotMiddleware
{ {
private readonly OcelotRequestDelegate _next; private readonly OcelotRequestDelegate _next;
private readonly IAddQueriesToRequest _addQueriesToRequest; private readonly IAddQueriesToRequest _addQueriesToRequest;
public QueryStringBuilderMiddleware(OcelotRequestDelegate next, public ClaimsToQueryStringMiddleware(OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory, IOcelotLoggerFactory loggerFactory,
IAddQueriesToRequest addQueriesToRequest) IAddQueriesToRequest addQueriesToRequest)
: base(loggerFactory.CreateLogger<QueryStringBuilderMiddleware>()) : base(loggerFactory.CreateLogger<ClaimsToQueryStringMiddleware>())
{ {
_next = next; _next = next;
_addQueriesToRequest = addQueriesToRequest; _addQueriesToRequest = addQueriesToRequest;
} }
public async Task Invoke(DownstreamContext context) public async Task Invoke(DownstreamContext context)
{ {
if (context.DownstreamReRoute.ClaimsToQueries.Any()) if (context.DownstreamReRoute.ClaimsToQueries.Any())
{ {
Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to queries"); Logger.LogInformation($"{context.DownstreamReRoute.DownstreamPathTemplate.Value} has instructions to convert claims to queries");
var response = _addQueriesToRequest.SetQueriesOnDownstreamRequest(context.DownstreamReRoute.ClaimsToQueries, context.HttpContext.User.Claims, context.DownstreamRequest); var response = _addQueriesToRequest.SetQueriesOnDownstreamRequest(context.DownstreamReRoute.ClaimsToQueries, context.HttpContext.User.Claims, context.DownstreamRequest);
if (response.IsError) if (response.IsError)
{ {
Logger.LogWarning("there was an error setting queries on context, setting pipeline error"); Logger.LogWarning("there was an error setting queries on context, setting pipeline error");
SetPipelineError(context, response.Errors); SetPipelineError(context, response.Errors);
return; return;
} }
} }
await _next.Invoke(context); await _next.Invoke(context);
} }
} }
} }

View File

@ -0,0 +1,13 @@
namespace Ocelot.QueryStrings.Middleware
{
using Microsoft.AspNetCore.Builder;
using Ocelot.Middleware.Pipeline;
public static class ClaimsToQueryStringMiddlewareExtensions
{
public static IOcelotPipelineBuilder UseClaimsToQueryStringMiddleware(this IOcelotPipelineBuilder builder)
{
return builder.UseMiddleware<ClaimsToQueryStringMiddleware>();
}
}
}

View File

@ -1,13 +0,0 @@
using Microsoft.AspNetCore.Builder;
using Ocelot.Middleware.Pipeline;
namespace Ocelot.QueryStrings.Middleware
{
public static class QueryStringBuilderMiddlewareExtensions
{
public static IOcelotPipelineBuilder UseQueryStringBuilderMiddleware(this IOcelotPipelineBuilder builder)
{
return builder.UseMiddleware<QueryStringBuilderMiddleware>();
}
}
}

View File

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.IO;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Ocelot.Configuration.File;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Middleware;
using Ocelot.DependencyInjection;
using System.Net.Http;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes.Jobs;
using Ocelot.Configuration.Repository;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Errors.Middleware;
using Microsoft.Extensions.DependencyInjection;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Validators;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.DownstreamRouteFinder.Finder;
using Ocelot.Middleware.Multiplexer;
namespace Ocelot.Benchmarks
{
[SimpleJob(launchCount: 1, warmupCount: 2, targetCount: 5)]
[Config(typeof(DownstreamRouteFinderMiddlewareBenchmarks))]
public class DownstreamRouteFinderMiddlewareBenchmarks : ManualConfig
{
private DownstreamRouteFinderMiddleware _middleware;
private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
public DownstreamRouteFinderMiddlewareBenchmarks()
{
Add(StatisticColumn.AllStatistics);
Add(MemoryDiagnoser.Default);
Add(BaselineValidator.FailOnError);
}
[GlobalSetup]
public void SetUp()
{
var serviceCollection = new ServiceCollection();
var config = new ConfigurationRoot(new List<IConfigurationProvider>());
var builder = new OcelotBuilder(serviceCollection, config);
var services = serviceCollection.BuildServiceProvider();
var loggerFactory = services.GetService<IOcelotLoggerFactory>();
var drpf = services.GetService<IDownstreamRouteProviderFactory>();
var icr = services.GetService<IInternalConfigurationRepository>();
var multiplexer = services.GetService<IMultiplexer>();
_next = async context => {
await Task.CompletedTask;
throw new Exception("BOOM");
};
_middleware = new DownstreamRouteFinderMiddleware(_next, loggerFactory, drpf, icr, multiplexer);
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
}
[Benchmark(Baseline = true)]
public async Task Baseline()
{
await _middleware.Invoke(_downstreamContext);
}
}
}

View File

@ -1,89 +1,89 @@
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.UnitTests.Claims namespace Ocelot.UnitTests.Claims
{ {
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Moq; using Moq;
using Ocelot.Claims; using Ocelot.Claims;
using Ocelot.Claims.Middleware; using Ocelot.Claims.Middleware;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Responses; using Ocelot.Responses;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
public class ClaimsBuilderMiddlewareTests public class ClaimsToClaimsMiddlewareTests
{ {
private readonly Mock<IAddClaimsToRequest> _addHeaders; private readonly Mock<IAddClaimsToRequest> _addHeaders;
private Mock<IOcelotLoggerFactory> _loggerFactory; private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger; private Mock<IOcelotLogger> _logger;
private readonly ClaimsBuilderMiddleware _middleware; private readonly ClaimsToClaimsMiddleware _middleware;
private readonly DownstreamContext _downstreamContext; private readonly DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next; private OcelotRequestDelegate _next;
public ClaimsBuilderMiddlewareTests() public ClaimsToClaimsMiddlewareTests()
{ {
_addHeaders = new Mock<IAddClaimsToRequest>(); _addHeaders = new Mock<IAddClaimsToRequest>();
_downstreamContext = new DownstreamContext(new DefaultHttpContext()); _downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>(); _loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>(); _logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<ClaimsBuilderMiddleware>()).Returns(_logger.Object); _loggerFactory.Setup(x => x.CreateLogger<ClaimsToClaimsMiddleware>()).Returns(_logger.Object);
_next = context => Task.CompletedTask; _next = context => Task.CompletedTask;
_middleware = new ClaimsBuilderMiddleware(_next, _loggerFactory.Object, _addHeaders.Object); _middleware = new ClaimsToClaimsMiddleware(_next, _loggerFactory.Object, _addHeaders.Object);
} }
[Fact] [Fact]
public void should_call_claims_to_request_correctly() public void should_call_claims_to_request_correctly()
{ {
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(), var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder() new ReRouteBuilder()
.WithDownstreamReRoute(new DownstreamReRouteBuilder() .WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("any old string") .WithDownstreamPathTemplate("any old string")
.WithClaimsToClaims(new List<ClaimToThing> .WithClaimsToClaims(new List<ClaimToThing>
{ {
new ClaimToThing("sub", "UserType", "|", 0) new ClaimToThing("sub", "UserType", "|", 0)
}) })
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()) .Build())
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()); .Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => x.GivenTheAddClaimsToRequestReturns()) .And(x => x.GivenTheAddClaimsToRequestReturns())
.When(x => x.WhenICallTheMiddleware()) .When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheClaimsToRequestIsCalledCorrectly()) .Then(x => x.ThenTheClaimsToRequestIsCalledCorrectly())
.BDDfy(); .BDDfy();
} }
private void WhenICallTheMiddleware() private void WhenICallTheMiddleware()
{ {
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult(); _middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
} }
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute) private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
{ {
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues; _downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0]; _downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
} }
private void GivenTheAddClaimsToRequestReturns() private void GivenTheAddClaimsToRequestReturns()
{ {
_addHeaders _addHeaders
.Setup(x => x.SetClaimsOnContext(It.IsAny<List<ClaimToThing>>(), .Setup(x => x.SetClaimsOnContext(It.IsAny<List<ClaimToThing>>(),
It.IsAny<HttpContext>())) It.IsAny<HttpContext>()))
.Returns(new OkResponse()); .Returns(new OkResponse());
} }
private void ThenTheClaimsToRequestIsCalledCorrectly() private void ThenTheClaimsToRequestIsCalledCorrectly()
{ {
_addHeaders _addHeaders
.Verify(x => x.SetClaimsOnContext(It.IsAny<List<ClaimToThing>>(), .Verify(x => x.SetClaimsOnContext(It.IsAny<List<ClaimToThing>>(),
It.IsAny<HttpContext>()), Times.Once); It.IsAny<HttpContext>()), Times.Once);
} }
} }
} }

View File

@ -1,98 +1,98 @@
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.UnitTests.Headers namespace Ocelot.UnitTests.Headers
{ {
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Moq; using Moq;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Headers; using Ocelot.Headers;
using Ocelot.Headers.Middleware; using Ocelot.Headers.Middleware;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.Request.Middleware; using Ocelot.Request.Middleware;
using Ocelot.Responses; using Ocelot.Responses;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
public class HttpRequestHeadersBuilderMiddlewareTests public class ClaimsToHeadersMiddlewareTests
{ {
private readonly Mock<IAddHeadersToRequest> _addHeaders; private readonly Mock<IAddHeadersToRequest> _addHeaders;
private Response<DownstreamRoute> _downstreamRoute; private Response<DownstreamRoute> _downstreamRoute;
private Mock<IOcelotLoggerFactory> _loggerFactory; private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger; private Mock<IOcelotLogger> _logger;
private HttpRequestHeadersBuilderMiddleware _middleware; private ClaimsToHeadersMiddleware _middleware;
private DownstreamContext _downstreamContext; private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next; private OcelotRequestDelegate _next;
public HttpRequestHeadersBuilderMiddlewareTests() public ClaimsToHeadersMiddlewareTests()
{ {
_addHeaders = new Mock<IAddHeadersToRequest>(); _addHeaders = new Mock<IAddHeadersToRequest>();
_downstreamContext = new DownstreamContext(new DefaultHttpContext()); _downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>(); _loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>(); _logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<HttpRequestHeadersBuilderMiddleware>()).Returns(_logger.Object); _loggerFactory.Setup(x => x.CreateLogger<ClaimsToHeadersMiddleware>()).Returns(_logger.Object);
_next = context => Task.CompletedTask; _next = context => Task.CompletedTask;
_middleware = new HttpRequestHeadersBuilderMiddleware(_next, _loggerFactory.Object, _addHeaders.Object); _middleware = new ClaimsToHeadersMiddleware(_next, _loggerFactory.Object, _addHeaders.Object);
_downstreamContext.DownstreamRequest = new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com")); _downstreamContext.DownstreamRequest = new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com"));
} }
[Fact] [Fact]
public void should_call_add_headers_to_request_correctly() public void should_call_add_headers_to_request_correctly()
{ {
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(), var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder() new ReRouteBuilder()
.WithDownstreamReRoute(new DownstreamReRouteBuilder() .WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("any old string") .WithDownstreamPathTemplate("any old string")
.WithClaimsToHeaders(new List<ClaimToThing> .WithClaimsToHeaders(new List<ClaimToThing>
{ {
new ClaimToThing("UserId", "Subject", "", 0) new ClaimToThing("UserId", "Subject", "", 0)
}) })
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()) .Build())
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()); .Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => x.GivenTheAddHeadersToDownstreamRequestReturnsOk()) .And(x => x.GivenTheAddHeadersToDownstreamRequestReturnsOk())
.When(x => x.WhenICallTheMiddleware()) .When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheAddHeadersToRequestIsCalledCorrectly()) .Then(x => x.ThenTheAddHeadersToRequestIsCalledCorrectly())
.BDDfy(); .BDDfy();
} }
private void WhenICallTheMiddleware() private void WhenICallTheMiddleware()
{ {
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult(); _middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
} }
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute) private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
{ {
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute); _downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues; _downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0]; _downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
} }
private void GivenTheAddHeadersToDownstreamRequestReturnsOk() private void GivenTheAddHeadersToDownstreamRequestReturnsOk()
{ {
_addHeaders _addHeaders
.Setup(x => x.SetHeadersOnDownstreamRequest( .Setup(x => x.SetHeadersOnDownstreamRequest(
It.IsAny<List<ClaimToThing>>(), It.IsAny<List<ClaimToThing>>(),
It.IsAny<IEnumerable<System.Security.Claims.Claim>>(), It.IsAny<IEnumerable<System.Security.Claims.Claim>>(),
It.IsAny<DownstreamRequest>())) It.IsAny<DownstreamRequest>()))
.Returns(new OkResponse()); .Returns(new OkResponse());
} }
private void ThenTheAddHeadersToRequestIsCalledCorrectly() private void ThenTheAddHeadersToRequestIsCalledCorrectly()
{ {
_addHeaders _addHeaders
.Verify(x => x.SetHeadersOnDownstreamRequest( .Verify(x => x.SetHeadersOnDownstreamRequest(
It.IsAny<List<ClaimToThing>>(), It.IsAny<List<ClaimToThing>>(),
It.IsAny<IEnumerable<System.Security.Claims.Claim>>(), It.IsAny<IEnumerable<System.Security.Claims.Claim>>(),
_downstreamContext.DownstreamRequest), Times.Once); _downstreamContext.DownstreamRequest), Times.Once);
} }
} }
} }

View File

@ -1,97 +1,97 @@
using Ocelot.Middleware; using Ocelot.Middleware;
namespace Ocelot.UnitTests.QueryStrings namespace Ocelot.UnitTests.QueryStrings
{ {
using System.Collections.Generic; using System.Collections.Generic;
using System.Net.Http; using System.Net.Http;
using Moq; using Moq;
using Ocelot.Configuration; using Ocelot.Configuration;
using Ocelot.Configuration.Builder; using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder; using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher; using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Logging; using Ocelot.Logging;
using Ocelot.QueryStrings; using Ocelot.QueryStrings;
using Ocelot.QueryStrings.Middleware; using Ocelot.QueryStrings.Middleware;
using Ocelot.Responses; using Ocelot.Responses;
using TestStack.BDDfy; using TestStack.BDDfy;
using Xunit; using Xunit;
using System.Security.Claims; using System.Security.Claims;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ocelot.Request.Middleware; using Ocelot.Request.Middleware;
public class QueryStringBuilderMiddlewareTests public class ClaimsToQueryStringMiddlewareTests
{ {
private readonly Mock<IAddQueriesToRequest> _addQueries; private readonly Mock<IAddQueriesToRequest> _addQueries;
private Mock<IOcelotLoggerFactory> _loggerFactory; private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger; private Mock<IOcelotLogger> _logger;
private QueryStringBuilderMiddleware _middleware; private ClaimsToQueryStringMiddleware _middleware;
private DownstreamContext _downstreamContext; private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next; private OcelotRequestDelegate _next;
public QueryStringBuilderMiddlewareTests() public ClaimsToQueryStringMiddlewareTests()
{ {
_downstreamContext = new DownstreamContext(new DefaultHttpContext()); _downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>(); _loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>(); _logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<QueryStringBuilderMiddleware>()).Returns(_logger.Object); _loggerFactory.Setup(x => x.CreateLogger<ClaimsToQueryStringMiddleware>()).Returns(_logger.Object);
_next = context => Task.CompletedTask; _next = context => Task.CompletedTask;
_addQueries = new Mock<IAddQueriesToRequest>(); _addQueries = new Mock<IAddQueriesToRequest>();
_downstreamContext.DownstreamRequest = new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com")); _downstreamContext.DownstreamRequest = new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com"));
_middleware = new QueryStringBuilderMiddleware(_next, _loggerFactory.Object, _addQueries.Object); _middleware = new ClaimsToQueryStringMiddleware(_next, _loggerFactory.Object, _addQueries.Object);
} }
[Fact] [Fact]
public void should_call_add_queries_correctly() public void should_call_add_queries_correctly()
{ {
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(), var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder() new ReRouteBuilder()
.WithDownstreamReRoute(new DownstreamReRouteBuilder() .WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("any old string") .WithDownstreamPathTemplate("any old string")
.WithClaimsToQueries(new List<ClaimToThing> .WithClaimsToQueries(new List<ClaimToThing>
{ {
new ClaimToThing("UserId", "Subject", "", 0) new ClaimToThing("UserId", "Subject", "", 0)
}) })
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()) .Build())
.WithUpstreamHttpMethod(new List<string> { "Get" }) .WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()); .Build());
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute)) this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => x.GivenTheAddHeadersToRequestReturnsOk()) .And(x => x.GivenTheAddHeadersToRequestReturnsOk())
.When(x => x.WhenICallTheMiddleware()) .When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheAddQueriesToRequestIsCalledCorrectly()) .Then(x => x.ThenTheAddQueriesToRequestIsCalledCorrectly())
.BDDfy(); .BDDfy();
} }
private void WhenICallTheMiddleware() private void WhenICallTheMiddleware()
{ {
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult(); _middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
} }
private void GivenTheAddHeadersToRequestReturnsOk() private void GivenTheAddHeadersToRequestReturnsOk()
{ {
_addQueries _addQueries
.Setup(x => x.SetQueriesOnDownstreamRequest( .Setup(x => x.SetQueriesOnDownstreamRequest(
It.IsAny<List<ClaimToThing>>(), It.IsAny<List<ClaimToThing>>(),
It.IsAny<IEnumerable<Claim>>(), It.IsAny<IEnumerable<Claim>>(),
It.IsAny<DownstreamRequest>())) It.IsAny<DownstreamRequest>()))
.Returns(new OkResponse()); .Returns(new OkResponse());
} }
private void ThenTheAddQueriesToRequestIsCalledCorrectly() private void ThenTheAddQueriesToRequestIsCalledCorrectly()
{ {
_addQueries _addQueries
.Verify(x => x.SetQueriesOnDownstreamRequest( .Verify(x => x.SetQueriesOnDownstreamRequest(
It.IsAny<List<ClaimToThing>>(), It.IsAny<List<ClaimToThing>>(),
It.IsAny<IEnumerable<Claim>>(), It.IsAny<IEnumerable<Claim>>(),
_downstreamContext.DownstreamRequest), Times.Once); _downstreamContext.DownstreamRequest), Times.Once);
} }
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute) private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
{ {
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues; _downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0]; _downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
} }
} }
} }