mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-06-19 23:08:16 +08:00
Remove Ocelot specific Middleware to make Ocelot more compatible with kestrel middleware and get ready for YARP
This commit is contained in:
@ -1,115 +1,119 @@
|
||||
using Xunit;
|
||||
|
||||
[assembly: CollectionBehavior(DisableTestParallelization = true)]
|
||||
|
||||
namespace Ocelot.UnitTests.Authentication
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Authentication.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
[assembly: CollectionBehavior(DisableTestParallelization = true)]
|
||||
|
||||
namespace Ocelot.UnitTests.Authentication
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Authentication.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class AuthenticationMiddlewareTests
|
||||
{
|
||||
private AuthenticationMiddleware _middleware;
|
||||
private readonly Mock<IOcelotLoggerFactory> _factory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private OcelotRequestDelegate _next;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
|
||||
public AuthenticationMiddlewareTests()
|
||||
public class AuthenticationMiddlewareTests
|
||||
{
|
||||
private AuthenticationMiddleware _middleware;
|
||||
private readonly Mock<IOcelotLoggerFactory> _factory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
private Mock<IRequestScopedDataRepository> _repo;
|
||||
|
||||
public AuthenticationMiddlewareTests()
|
||||
{
|
||||
_repo = new Mock<IRequestScopedDataRepository>();
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_factory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_factory.Setup(x => x.CreateLogger<AuthenticationMiddleware>()).Returns(_logger.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_next_middleware_if_route_is_not_authenticated()
|
||||
{
|
||||
this.Given(x => GivenTheDownStreamRouteIs(
|
||||
new DownstreamReRouteBuilder().WithUpstreamHttpMethod(new List<string> { "Get" }).Build()))
|
||||
.And(x => GivenTheTestServerPipelineIsConfigured())
|
||||
.When(x => WhenICallTheMiddleware())
|
||||
.Then(x => ThenTheUserIsAuthenticated())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_next_middleware_if_route_is_using_options_method()
|
||||
{
|
||||
this.Given(x => GivenTheDownStreamRouteIs(
|
||||
new DownstreamReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(new List<string> { "Options" })
|
||||
.WithIsAuthenticated(true)
|
||||
.Build()))
|
||||
.And(x => GivenTheRequestIsUsingOptionsMethod())
|
||||
.When(x => WhenICallTheMiddleware())
|
||||
.Then(x => ThenTheUserIsAuthenticated())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_next = (context) =>
|
||||
{
|
||||
byte[] byteArray = Encoding.ASCII.GetBytes("The user is authenticated");
|
||||
var stream = new MemoryStream(byteArray);
|
||||
_httpContext.Response.Body = stream;
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
_middleware = new AuthenticationMiddleware(_next, _factory.Object);
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheTestServerPipelineIsConfigured()
|
||||
{
|
||||
_next = (context) =>
|
||||
{
|
||||
byte[] byteArray = Encoding.ASCII.GetBytes("The user is authenticated");
|
||||
var stream = new MemoryStream(byteArray);
|
||||
_httpContext.Response.Body = stream;
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenTheRequestIsUsingOptionsMethod()
|
||||
{
|
||||
_httpContext.Request.Method = "OPTIONS";
|
||||
}
|
||||
|
||||
private void ThenTheUserIsAuthenticated()
|
||||
{
|
||||
var content = _httpContext.Response.Body.AsString();
|
||||
content.ShouldBe("The user is authenticated");
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamReRoute downstreamRoute)
|
||||
{
|
||||
_factory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_factory.Setup(x => x.CreateLogger<AuthenticationMiddleware>()).Returns(_logger.Object);
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_next_middleware_if_route_is_not_authenticated()
|
||||
{
|
||||
this.Given(x => GivenTheDownStreamRouteIs(
|
||||
new DownstreamReRouteBuilder().WithUpstreamHttpMethod(new List<string> { "Get" }).Build()))
|
||||
.And(x => GivenTheTestServerPipelineIsConfigured())
|
||||
.When(x => WhenICallTheMiddleware())
|
||||
.Then(x => ThenTheUserIsAuthenticated())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_next_middleware_if_route_is_using_options_method()
|
||||
{
|
||||
this.Given(x => GivenTheDownStreamRouteIs(
|
||||
new DownstreamReRouteBuilder()
|
||||
.WithUpstreamHttpMethod(new List<string> { "Options" })
|
||||
.WithIsAuthenticated(true)
|
||||
.Build()))
|
||||
.And(x => GivenTheRequestIsUsingOptionsMethod())
|
||||
.When(x => WhenICallTheMiddleware())
|
||||
.Then(x => ThenTheUserIsAuthenticated())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_next = (context) =>
|
||||
{
|
||||
byte[] byteArray = Encoding.ASCII.GetBytes("The user is authenticated");
|
||||
var stream = new MemoryStream(byteArray);
|
||||
context.HttpContext.Response.Body = stream;
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
_middleware = new AuthenticationMiddleware(_next, _factory.Object);
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheTestServerPipelineIsConfigured()
|
||||
{
|
||||
_next = (context) =>
|
||||
{
|
||||
byte[] byteArray = Encoding.ASCII.GetBytes("The user is authenticated");
|
||||
var stream = new MemoryStream(byteArray);
|
||||
context.HttpContext.Response.Body = stream;
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenTheRequestIsUsingOptionsMethod()
|
||||
{
|
||||
_downstreamContext.HttpContext.Request.Method = "OPTIONS";
|
||||
}
|
||||
|
||||
private void ThenTheUserIsAuthenticated()
|
||||
{
|
||||
var content = _downstreamContext.HttpContext.Response.Body.AsString();
|
||||
content.ShouldBe("The user is authenticated");
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamReRoute downstreamRoute)
|
||||
{
|
||||
_downstreamContext.DownstreamReRoute = downstreamRoute;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StreamExtensions
|
||||
{
|
||||
public static string AsString(this Stream stream)
|
||||
{
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
string text = reader.ReadToEnd();
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_httpContext.Items.UpsertDownstreamReRoute(downstreamRoute);
|
||||
}
|
||||
}
|
||||
|
||||
public static class StreamExtensions
|
||||
{
|
||||
public static string AsString(this Stream stream)
|
||||
{
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
string text = reader.ReadToEnd();
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,88 +1,89 @@
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.Authorization
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Authorisation;
|
||||
using Ocelot.Authorisation.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Responses;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class AuthorisationMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IClaimsAuthoriser> _authService;
|
||||
private readonly Mock<IScopesAuthoriser> _authScopesService;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly AuthorisationMiddleware _middleware;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
|
||||
public AuthorisationMiddlewareTests()
|
||||
{
|
||||
_authService = new Mock<IClaimsAuthoriser>();
|
||||
_authScopesService = new Mock<IScopesAuthoriser>();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new AuthorisationMiddleware(_next, _authService.Object, _authScopesService.Object, _loggerFactory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_authorisation_service()
|
||||
{
|
||||
|
||||
namespace Ocelot.UnitTests.Authorization
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Authorisation;
|
||||
using Ocelot.Authorisation.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class AuthorisationMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IClaimsAuthoriser> _authService;
|
||||
private readonly Mock<IScopesAuthoriser> _authScopesService;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly AuthorisationMiddleware _middleware;
|
||||
private RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public AuthorisationMiddlewareTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_authService = new Mock<IClaimsAuthoriser>();
|
||||
_authScopesService = new Mock<IScopesAuthoriser>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new AuthorisationMiddleware(_next, _authService.Object, _authScopesService.Object, _loggerFactory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_authorisation_service()
|
||||
{
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(new List<PlaceholderNameAndValue>(),
|
||||
new DownstreamReRouteBuilder()
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().Build())
|
||||
.WithIsAuthorised(true)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build()))
|
||||
.And(x => x.GivenTheAuthServiceReturns(new OkResponse<bool>(true)))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheAuthServiceIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(List<PlaceholderNameAndValue> templatePlaceholderNameAndValues, DownstreamReRoute downstreamReRoute)
|
||||
{
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues = templatePlaceholderNameAndValues;
|
||||
_downstreamContext.DownstreamReRoute = downstreamReRoute;
|
||||
}
|
||||
|
||||
private void GivenTheAuthServiceReturns(Response<bool> expected)
|
||||
{
|
||||
_authService
|
||||
new DownstreamReRouteBuilder()
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().Build())
|
||||
.WithIsAuthorised(true)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build()))
|
||||
.And(x => x.GivenTheAuthServiceReturns(new OkResponse<bool>(true)))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheAuthServiceIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(List<PlaceholderNameAndValue> templatePlaceholderNameAndValues, DownstreamReRoute downstreamReRoute)
|
||||
{
|
||||
_httpContext.Items.UpsertTemplatePlaceholderNameAndValues(templatePlaceholderNameAndValues);
|
||||
_httpContext.Items.UpsertDownstreamReRoute(downstreamReRoute);
|
||||
}
|
||||
|
||||
private void GivenTheAuthServiceReturns(Response<bool> expected)
|
||||
{
|
||||
_authService
|
||||
.Setup(x => x.Authorise(
|
||||
It.IsAny<ClaimsPrincipal>(),
|
||||
It.IsAny<Dictionary<string, string>>(),
|
||||
It.IsAny<List<PlaceholderNameAndValue>>()))
|
||||
.Returns(expected);
|
||||
}
|
||||
|
||||
private void ThenTheAuthServiceIsCalledCorrectly()
|
||||
{
|
||||
_authService
|
||||
.Verify(x => x.Authorise(
|
||||
It.IsAny<ClaimsPrincipal>(),
|
||||
It.IsAny<Dictionary<string, string>>(),
|
||||
It.IsAny<List<PlaceholderNameAndValue>>()))
|
||||
.Returns(expected);
|
||||
}
|
||||
|
||||
private void ThenTheAuthServiceIsCalledCorrectly()
|
||||
{
|
||||
_authService
|
||||
.Verify(x => x.Authorise(
|
||||
It.IsAny<ClaimsPrincipal>(),
|
||||
It.IsAny<Dictionary<string, string>>(),
|
||||
It.IsAny<List<PlaceholderNameAndValue>>())
|
||||
, Times.Once);
|
||||
}
|
||||
}
|
||||
, Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +1,34 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Cache;
|
||||
using Ocelot.Middleware;
|
||||
using Shouldly;
|
||||
using System.Net.Http;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Cache
|
||||
namespace Ocelot.UnitTests.Cache
|
||||
{
|
||||
using Ocelot.Cache;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Shouldly;
|
||||
using System.Net.Http;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class CacheKeyGeneratorTests
|
||||
{
|
||||
private readonly ICacheKeyGenerator _cacheKeyGenerator;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private readonly DownstreamRequest _downstreamRequest;
|
||||
|
||||
public CacheKeyGeneratorTests()
|
||||
{
|
||||
_cacheKeyGenerator = new CacheKeyGenerator();
|
||||
_cacheKeyGenerator = new CacheKeyGenerator();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamRequest = new Ocelot.Request.Middleware.DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123"))
|
||||
};
|
||||
_downstreamRequest = new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_generate_cache_key_from_context()
|
||||
{
|
||||
this.Given(x => x.GivenCacheKeyFromContext(_downstreamContext))
|
||||
this.Given(x => x.GivenCacheKeyFromContext(_downstreamRequest))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenCacheKeyFromContext(DownstreamContext context)
|
||||
private void GivenCacheKeyFromContext(DownstreamRequest downstreamRequest)
|
||||
{
|
||||
string generatedCacheKey = _cacheKeyGenerator.GenerateRequestCacheKey(context);
|
||||
string generatedCacheKey = _cacheKeyGenerator.GenerateRequestCacheKey(downstreamRequest);
|
||||
string cachekey = MD5Helper.GenerateMd5("GET-https://some.url/blah?abcd=123");
|
||||
generatedCacheKey.ShouldBe(cachekey);
|
||||
}
|
||||
|
@ -1,140 +1,144 @@
|
||||
namespace Ocelot.UnitTests.Cache
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Cache;
|
||||
using Ocelot.Cache.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
namespace Ocelot.UnitTests.Cache
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Cache;
|
||||
using Ocelot.Cache.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class OutputCacheMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IOcelotCache<CachedResponse>> _cache;
|
||||
private readonly Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private OutputCacheMiddleware _middleware;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private readonly OcelotRequestDelegate _next;
|
||||
private readonly ICacheKeyGenerator _cacheKeyGenerator;
|
||||
private CachedResponse _response;
|
||||
|
||||
|
||||
public OutputCacheMiddlewareTests()
|
||||
{
|
||||
_cache = new Mock<IOcelotCache<CachedResponse>>();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_cacheKeyGenerator = new CacheKeyGenerator();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<OutputCacheMiddleware>()).Returns(_logger.Object);
|
||||
public class OutputCacheMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IOcelotCache<CachedResponse>> _cache;
|
||||
private readonly Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private OutputCacheMiddleware _middleware;
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly ICacheKeyGenerator _cacheKeyGenerator;
|
||||
private CachedResponse _response;
|
||||
private HttpContext _httpContext;
|
||||
private Mock<IRequestScopedDataRepository> _repo;
|
||||
|
||||
public OutputCacheMiddlewareTests()
|
||||
{
|
||||
_repo = new Mock<IRequestScopedDataRepository>();
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_cache = new Mock<IOcelotCache<CachedResponse>>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_cacheKeyGenerator = new CacheKeyGenerator();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<OutputCacheMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_downstreamContext.DownstreamRequest = new Ocelot.Request.Middleware.DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_returned_cached_item_when_it_is_in_cache()
|
||||
_httpContext.Items.UpsertDownstreamRequest(new Ocelot.Request.Middleware.DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_returned_cached_item_when_it_is_in_cache()
|
||||
{
|
||||
var headers = new Dictionary<string, IEnumerable<string>>
|
||||
{
|
||||
{ "test", new List<string> { "test" } }
|
||||
};
|
||||
|
||||
var contentHeaders = new Dictionary<string, IEnumerable<string>>
|
||||
{
|
||||
{ "content-type", new List<string> { "application/json" } }
|
||||
};
|
||||
|
||||
var cachedResponse = new CachedResponse(HttpStatusCode.OK, headers, "", contentHeaders, "some reason");
|
||||
this.Given(x => x.GivenThereIsACachedResponse(cachedResponse))
|
||||
.And(x => x.GivenTheDownstreamRouteIs())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheCacheGetIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_returned_cached_item_when_it_is_in_cache_expires_header()
|
||||
{
|
||||
var contentHeaders = new Dictionary<string, IEnumerable<string>>
|
||||
{
|
||||
{ "Expires", new List<string> { "-1" } }
|
||||
};
|
||||
|
||||
var cachedResponse = new CachedResponse(HttpStatusCode.OK, new Dictionary<string, IEnumerable<string>>(), "", contentHeaders, "some reason");
|
||||
this.Given(x => x.GivenThereIsACachedResponse(cachedResponse))
|
||||
.And(x => x.GivenTheDownstreamRouteIs())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheCacheGetIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_continue_with_pipeline_and_cache_response()
|
||||
{
|
||||
this.Given(x => x.GivenResponseIsNotCached(new HttpResponseMessage()))
|
||||
.And(x => x.GivenTheDownstreamRouteIs())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheCacheAddIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware = new OutputCacheMiddleware(_next, _loggerFactory.Object, _cache.Object, _cacheKeyGenerator);
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenThereIsACachedResponse(CachedResponse response)
|
||||
{
|
||||
_response = response;
|
||||
_cache
|
||||
.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Returns(_response);
|
||||
}
|
||||
|
||||
private void GivenResponseIsNotCached(HttpResponseMessage responseMessage)
|
||||
{
|
||||
var headers = new Dictionary<string, IEnumerable<string>>
|
||||
{
|
||||
{ "test", new List<string> { "test" } }
|
||||
};
|
||||
|
||||
var contentHeaders = new Dictionary<string, IEnumerable<string>>
|
||||
{
|
||||
{ "content-type", new List<string> { "application/json" } }
|
||||
};
|
||||
|
||||
var cachedResponse = new CachedResponse(HttpStatusCode.OK, headers, "", contentHeaders, "some reason");
|
||||
this.Given(x => x.GivenThereIsACachedResponse(cachedResponse))
|
||||
.And(x => x.GivenTheDownstreamRouteIs())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheCacheGetIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_returned_cached_item_when_it_is_in_cache_expires_header()
|
||||
{
|
||||
var contentHeaders = new Dictionary<string, IEnumerable<string>>
|
||||
{
|
||||
{ "Expires", new List<string> { "-1" } }
|
||||
};
|
||||
|
||||
var cachedResponse = new CachedResponse(HttpStatusCode.OK, new Dictionary<string, IEnumerable<string>>(), "", contentHeaders, "some reason");
|
||||
this.Given(x => x.GivenThereIsACachedResponse(cachedResponse))
|
||||
.And(x => x.GivenTheDownstreamRouteIs())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheCacheGetIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_continue_with_pipeline_and_cache_response()
|
||||
{
|
||||
this.Given(x => x.GivenResponseIsNotCached(new HttpResponseMessage()))
|
||||
.And(x => x.GivenTheDownstreamRouteIs())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheCacheAddIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware = new OutputCacheMiddleware(_next, _loggerFactory.Object, _cache.Object, _cacheKeyGenerator);
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenThereIsACachedResponse(CachedResponse response)
|
||||
{
|
||||
_response = response;
|
||||
_cache
|
||||
.Setup(x => x.Get(It.IsAny<string>(), It.IsAny<string>()))
|
||||
.Returns(_response);
|
||||
}
|
||||
|
||||
private void GivenResponseIsNotCached(HttpResponseMessage responseMessage)
|
||||
{
|
||||
_downstreamContext.DownstreamResponse = new DownstreamResponse(responseMessage);
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRouteIs()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithIsCached(true)
|
||||
.WithCacheOptions(new CacheOptions(100, "kanken"))
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
_httpContext.Items.UpsertDownstreamResponse(new DownstreamResponse(responseMessage));
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRouteIs()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithIsCached(true)
|
||||
.WithCacheOptions(new CacheOptions(100, "kanken"))
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute);
|
||||
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
|
||||
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
|
||||
}
|
||||
_httpContext.Items.UpsertTemplatePlaceholderNameAndValues(downstreamRoute.TemplatePlaceholderNameAndValues);
|
||||
|
||||
private void ThenTheCacheGetIsCalledCorrectly()
|
||||
{
|
||||
_cache
|
||||
.Verify(x => x.Get(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheCacheAddIsCalledCorrectly()
|
||||
{
|
||||
_cache
|
||||
.Verify(x => x.Add(It.IsAny<string>(), It.IsAny<CachedResponse>(), It.IsAny<TimeSpan>(), It.IsAny<string>()), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
_httpContext.Items.UpsertDownstreamReRoute(downstreamRoute.ReRoute.DownstreamReRoute[0]);
|
||||
}
|
||||
|
||||
private void ThenTheCacheGetIsCalledCorrectly()
|
||||
{
|
||||
_cache
|
||||
.Verify(x => x.Get(It.IsAny<string>(), It.IsAny<string>()), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheCacheAddIsCalledCorrectly()
|
||||
{
|
||||
_cache
|
||||
.Verify(x => x.Add(It.IsAny<string>(), It.IsAny<CachedResponse>(), It.IsAny<TimeSpan>(), It.IsAny<string>()), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,96 +1,97 @@
|
||||
namespace Ocelot.UnitTests.CacheManager
|
||||
{
|
||||
using global::CacheManager.Core;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Cache;
|
||||
using Ocelot.Cache.CacheManager;
|
||||
using Ocelot.Cache.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
namespace Ocelot.UnitTests.CacheManager
|
||||
{
|
||||
using global::CacheManager.Core;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Cache;
|
||||
using Ocelot.Cache.CacheManager;
|
||||
using Ocelot.Cache.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class OutputCacheMiddlewareRealCacheTests
|
||||
{
|
||||
private readonly IOcelotCache<CachedResponse> _cacheManager;
|
||||
private readonly ICacheKeyGenerator _cacheKeyGenerator;
|
||||
private readonly OutputCacheMiddleware _middleware;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
|
||||
public OutputCacheMiddlewareRealCacheTests()
|
||||
{
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<OutputCacheMiddleware>()).Returns(_logger.Object);
|
||||
var cacheManagerOutputCache = CacheFactory.Build<CachedResponse>("OcelotOutputCache", x =>
|
||||
{
|
||||
x.WithDictionaryHandle();
|
||||
});
|
||||
_cacheManager = new OcelotCacheManagerCache<CachedResponse>(cacheManagerOutputCache);
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class OutputCacheMiddlewareRealCacheTests
|
||||
{
|
||||
private readonly IOcelotCache<CachedResponse> _cacheManager;
|
||||
private readonly ICacheKeyGenerator _cacheKeyGenerator;
|
||||
private readonly OutputCacheMiddleware _middleware;
|
||||
private RequestDelegate _next;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public OutputCacheMiddlewareRealCacheTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<OutputCacheMiddleware>()).Returns(_logger.Object);
|
||||
var cacheManagerOutputCache = CacheFactory.Build<CachedResponse>("OcelotOutputCache", x =>
|
||||
{
|
||||
x.WithDictionaryHandle();
|
||||
});
|
||||
_cacheManager = new OcelotCacheManagerCache<CachedResponse>(cacheManagerOutputCache);
|
||||
_cacheKeyGenerator = new CacheKeyGenerator();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_downstreamContext.DownstreamRequest = new Ocelot.Request.Middleware.DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123"));
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new OutputCacheMiddleware(_next, _loggerFactory.Object, _cacheManager, _cacheKeyGenerator);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_cache_content_headers()
|
||||
{
|
||||
var content = new StringContent("{\"Test\": 1}")
|
||||
{
|
||||
Headers = { ContentType = new MediaTypeHeaderValue("application/json") }
|
||||
};
|
||||
|
||||
var response = new DownstreamResponse(content, HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "fooreason");
|
||||
|
||||
this.Given(x => x.GivenResponseIsNotCached(response))
|
||||
.And(x => x.GivenTheDownstreamRouteIs())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheContentTypeHeaderIsCached())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThenTheContentTypeHeaderIsCached()
|
||||
{
|
||||
string cacheKey = MD5Helper.GenerateMd5("GET-https://some.url/blah?abcd=123");
|
||||
var result = _cacheManager.Get(cacheKey, "kanken");
|
||||
var header = result.ContentHeaders["Content-Type"];
|
||||
header.First().ShouldBe("application/json");
|
||||
}
|
||||
|
||||
private void GivenResponseIsNotCached(DownstreamResponse response)
|
||||
{
|
||||
_downstreamContext.DownstreamResponse = response;
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRouteIs()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithIsCached(true)
|
||||
.WithCacheOptions(new CacheOptions(100, "kanken"))
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
_httpContext.Items.UpsertDownstreamRequest(new Ocelot.Request.Middleware.DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123")));
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new OutputCacheMiddleware(_next, _loggerFactory.Object, _cacheManager, _cacheKeyGenerator);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_cache_content_headers()
|
||||
{
|
||||
var content = new StringContent("{\"Test\": 1}")
|
||||
{
|
||||
Headers = { ContentType = new MediaTypeHeaderValue("application/json") }
|
||||
};
|
||||
|
||||
var response = new DownstreamResponse(content, HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "fooreason");
|
||||
|
||||
this.Given(x => x.GivenResponseIsNotCached(response))
|
||||
.And(x => x.GivenTheDownstreamRouteIs())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheContentTypeHeaderIsCached())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThenTheContentTypeHeaderIsCached()
|
||||
{
|
||||
string cacheKey = MD5Helper.GenerateMd5("GET-https://some.url/blah?abcd=123");
|
||||
var result = _cacheManager.Get(cacheKey, "kanken");
|
||||
var header = result.ContentHeaders["Content-Type"];
|
||||
header.First().ShouldBe("application/json");
|
||||
}
|
||||
|
||||
private void GivenResponseIsNotCached(DownstreamResponse response)
|
||||
{
|
||||
_httpContext.Items.UpsertDownstreamResponse(response);
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRouteIs()
|
||||
{
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithIsCached(true)
|
||||
.WithCacheOptions(new CacheOptions(100, "kanken"))
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
_downstreamContext.DownstreamReRoute = reRoute;
|
||||
}
|
||||
}
|
||||
}
|
||||
_httpContext.Items.UpsertDownstreamReRoute(reRoute);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,142 +1,142 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Claims;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Infrastructure.Claims.Parser;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Claims
|
||||
{
|
||||
public class AddClaimsToRequestTests
|
||||
{
|
||||
private readonly AddClaimsToRequest _addClaimsToRequest;
|
||||
private readonly Mock<IClaimsParser> _parser;
|
||||
private List<ClaimToThing> _claimsToThings;
|
||||
private HttpContext _context;
|
||||
private Response _result;
|
||||
private Response<string> _claimValue;
|
||||
|
||||
public AddClaimsToRequestTests()
|
||||
{
|
||||
_parser = new Mock<IClaimsParser>();
|
||||
_addClaimsToRequest = new AddClaimsToRequest(_parser.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_claims_to_context()
|
||||
{
|
||||
var context = new DefaultHttpContext
|
||||
{
|
||||
User = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
|
||||
{
|
||||
new Claim("test", "data")
|
||||
}))
|
||||
};
|
||||
|
||||
this.Given(
|
||||
x => x.GivenClaimsToThings(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("claim-key", "", "", 0)
|
||||
}))
|
||||
.Given(x => x.GivenHttpContext(context))
|
||||
.And(x => x.GivenTheClaimParserReturns(new OkResponse<string>("value")))
|
||||
.When(x => x.WhenIAddClaimsToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsSuccess())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void if_claims_exists_should_replace_it()
|
||||
{
|
||||
var context = new DefaultHttpContext
|
||||
{
|
||||
User = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
|
||||
{
|
||||
new Claim("existing-key", "data"),
|
||||
new Claim("new-key", "data")
|
||||
})),
|
||||
};
|
||||
|
||||
this.Given(
|
||||
x => x.GivenClaimsToThings(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("existing-key", "new-key", "", 0)
|
||||
}))
|
||||
.Given(x => x.GivenHttpContext(context))
|
||||
.And(x => x.GivenTheClaimParserReturns(new OkResponse<string>("value")))
|
||||
.When(x => x.WhenIAddClaimsToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsSuccess())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error()
|
||||
{
|
||||
this.Given(
|
||||
x => x.GivenClaimsToThings(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("", "", "", 0)
|
||||
}))
|
||||
.Given(x => x.GivenHttpContext(new DefaultHttpContext()))
|
||||
.And(x => x.GivenTheClaimParserReturns(new ErrorResponse<string>(new List<Error>
|
||||
{
|
||||
new AnyError()
|
||||
})))
|
||||
.When(x => x.WhenIAddClaimsToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsError())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenClaimsToThings(List<ClaimToThing> configuration)
|
||||
{
|
||||
_claimsToThings = configuration;
|
||||
}
|
||||
|
||||
private void GivenHttpContext(HttpContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
private void GivenTheClaimParserReturns(Response<string> claimValue)
|
||||
{
|
||||
_claimValue = claimValue;
|
||||
_parser
|
||||
.Setup(
|
||||
x =>
|
||||
x.GetValue(It.IsAny<IEnumerable<Claim>>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<int>()))
|
||||
.Returns(_claimValue);
|
||||
}
|
||||
|
||||
private void WhenIAddClaimsToTheRequest()
|
||||
{
|
||||
_result = _addClaimsToRequest.SetClaimsOnContext(_claimsToThings, _context);
|
||||
}
|
||||
|
||||
private void ThenTheResultIsSuccess()
|
||||
{
|
||||
_result.IsError.ShouldBe(false);
|
||||
}
|
||||
|
||||
private void ThenTheResultIsError()
|
||||
{
|
||||
_result.IsError.ShouldBe(true);
|
||||
}
|
||||
|
||||
private class AnyError : Error
|
||||
{
|
||||
public AnyError()
|
||||
: base("blahh", OcelotErrorCode.UnknownError)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Claims;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Infrastructure.Claims.Parser;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Claims
|
||||
{
|
||||
public class AddClaimsToRequestTests
|
||||
{
|
||||
private readonly AddClaimsToRequest _addClaimsToRequest;
|
||||
private readonly Mock<IClaimsParser> _parser;
|
||||
private List<ClaimToThing> _claimsToThings;
|
||||
private HttpContext _context;
|
||||
private Response _result;
|
||||
private Response<string> _claimValue;
|
||||
|
||||
public AddClaimsToRequestTests()
|
||||
{
|
||||
_parser = new Mock<IClaimsParser>();
|
||||
_addClaimsToRequest = new AddClaimsToRequest(_parser.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_claims_to_context()
|
||||
{
|
||||
var context = new DefaultHttpContext
|
||||
{
|
||||
User = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
|
||||
{
|
||||
new Claim("test", "data")
|
||||
}))
|
||||
};
|
||||
|
||||
this.Given(
|
||||
x => x.GivenClaimsToThings(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("claim-key", "", "", 0)
|
||||
}))
|
||||
.Given(x => x.GivenHttpContext(context))
|
||||
.And(x => x.GivenTheClaimParserReturns(new OkResponse<string>("value")))
|
||||
.When(x => x.WhenIAddClaimsToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsSuccess())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void if_claims_exists_should_replace_it()
|
||||
{
|
||||
var context = new DefaultHttpContext
|
||||
{
|
||||
User = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
|
||||
{
|
||||
new Claim("existing-key", "data"),
|
||||
new Claim("new-key", "data")
|
||||
})),
|
||||
};
|
||||
|
||||
this.Given(
|
||||
x => x.GivenClaimsToThings(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("existing-key", "new-key", "", 0)
|
||||
}))
|
||||
.Given(x => x.GivenHttpContext(context))
|
||||
.And(x => x.GivenTheClaimParserReturns(new OkResponse<string>("value")))
|
||||
.When(x => x.WhenIAddClaimsToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsSuccess())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error()
|
||||
{
|
||||
this.Given(
|
||||
x => x.GivenClaimsToThings(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("", "", "", 0)
|
||||
}))
|
||||
.Given(x => x.GivenHttpContext(new DefaultHttpContext()))
|
||||
.And(x => x.GivenTheClaimParserReturns(new ErrorResponse<string>(new List<Error>
|
||||
{
|
||||
new AnyError()
|
||||
})))
|
||||
.When(x => x.WhenIAddClaimsToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsError())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenClaimsToThings(List<ClaimToThing> configuration)
|
||||
{
|
||||
_claimsToThings = configuration;
|
||||
}
|
||||
|
||||
private void GivenHttpContext(HttpContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
private void GivenTheClaimParserReturns(Response<string> claimValue)
|
||||
{
|
||||
_claimValue = claimValue;
|
||||
_parser
|
||||
.Setup(
|
||||
x =>
|
||||
x.GetValue(It.IsAny<IEnumerable<Claim>>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<int>()))
|
||||
.Returns(_claimValue);
|
||||
}
|
||||
|
||||
private void WhenIAddClaimsToTheRequest()
|
||||
{
|
||||
_result = _addClaimsToRequest.SetClaimsOnContext(_claimsToThings, _context);
|
||||
}
|
||||
|
||||
private void ThenTheResultIsSuccess()
|
||||
{
|
||||
_result.IsError.ShouldBe(false);
|
||||
}
|
||||
|
||||
private void ThenTheResultIsError()
|
||||
{
|
||||
_result.IsError.ShouldBe(true);
|
||||
}
|
||||
|
||||
private class AnyError : Error
|
||||
{
|
||||
public AnyError()
|
||||
: base("blahh", OcelotErrorCode.UnknownError, 404)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,89 +1,91 @@
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.Claims
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Claims;
|
||||
using Ocelot.Claims.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.Claims
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Claims;
|
||||
using Ocelot.Claims.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Responses;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class ClaimsToClaimsMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IAddClaimsToRequest> _addHeaders;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly ClaimsToClaimsMiddleware _middleware;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
|
||||
public ClaimsToClaimsMiddlewareTests()
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Responses;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class ClaimsToClaimsMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IAddClaimsToRequest> _addHeaders;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly ClaimsToClaimsMiddleware _middleware;
|
||||
private RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public ClaimsToClaimsMiddlewareTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_addHeaders = new Mock<IAddClaimsToRequest>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ClaimsToClaimsMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new ClaimsToClaimsMiddleware(_next, _loggerFactory.Object, _addHeaders.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_claims_to_request_correctly()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithClaimsToClaims(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("sub", "UserType", "|", 0)
|
||||
})
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => x.GivenTheAddClaimsToRequestReturns())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheClaimsToRequestIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_addHeaders = new Mock<IAddClaimsToRequest>();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ClaimsToClaimsMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new ClaimsToClaimsMiddleware(_next, _loggerFactory.Object, _addHeaders.Object);
|
||||
}
|
||||
_httpContext.Items.UpsertTemplatePlaceholderNameAndValues(downstreamRoute.TemplatePlaceholderNameAndValues);
|
||||
|
||||
[Fact]
|
||||
public void should_call_claims_to_request_correctly()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithClaimsToClaims(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("sub", "UserType", "|", 0)
|
||||
})
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => x.GivenTheAddClaimsToRequestReturns())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheClaimsToRequestIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
|
||||
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
|
||||
}
|
||||
|
||||
private void GivenTheAddClaimsToRequestReturns()
|
||||
{
|
||||
_addHeaders
|
||||
.Setup(x => x.SetClaimsOnContext(It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<HttpContext>()))
|
||||
.Returns(new OkResponse());
|
||||
}
|
||||
|
||||
private void ThenTheClaimsToRequestIsCalledCorrectly()
|
||||
{
|
||||
_addHeaders
|
||||
.Verify(x => x.SetClaimsOnContext(It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<HttpContext>()), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
_httpContext.Items.UpsertDownstreamReRoute(downstreamRoute.ReRoute.DownstreamReRoute[0]);
|
||||
}
|
||||
|
||||
private void GivenTheAddClaimsToRequestReturns()
|
||||
{
|
||||
_addHeaders
|
||||
.Setup(x => x.SetClaimsOnContext(It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<HttpContext>()))
|
||||
.Returns(new OkResponse());
|
||||
}
|
||||
|
||||
private void ThenTheClaimsToRequestIsCalledCorrectly()
|
||||
{
|
||||
_addHeaders
|
||||
.Verify(x => x.SetClaimsOnContext(It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<HttpContext>()), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,135 +1,135 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.Configuration.Setter;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Controllers
|
||||
{
|
||||
using Ocelot.Configuration.Repository;
|
||||
|
||||
public class FileConfigurationControllerTests
|
||||
{
|
||||
private readonly FileConfigurationController _controller;
|
||||
private readonly Mock<IFileConfigurationRepository> _repo;
|
||||
private readonly Mock<IFileConfigurationSetter> _setter;
|
||||
private IActionResult _result;
|
||||
private FileConfiguration _fileConfiguration;
|
||||
private readonly Mock<IServiceProvider> _provider;
|
||||
|
||||
public FileConfigurationControllerTests()
|
||||
{
|
||||
_provider = new Mock<IServiceProvider>();
|
||||
_repo = new Mock<IFileConfigurationRepository>();
|
||||
_setter = new Mock<IFileConfigurationSetter>();
|
||||
_controller = new FileConfigurationController(_repo.Object, _setter.Object, _provider.Object);
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.Configuration.Setter;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Controllers
|
||||
{
|
||||
using Ocelot.Configuration.Repository;
|
||||
|
||||
public class FileConfigurationControllerTests
|
||||
{
|
||||
private readonly FileConfigurationController _controller;
|
||||
private readonly Mock<IFileConfigurationRepository> _repo;
|
||||
private readonly Mock<IFileConfigurationSetter> _setter;
|
||||
private IActionResult _result;
|
||||
private FileConfiguration _fileConfiguration;
|
||||
private readonly Mock<IServiceProvider> _provider;
|
||||
|
||||
public FileConfigurationControllerTests()
|
||||
{
|
||||
_provider = new Mock<IServiceProvider>();
|
||||
_repo = new Mock<IFileConfigurationRepository>();
|
||||
_setter = new Mock<IFileConfigurationSetter>();
|
||||
_controller = new FileConfigurationController(_repo.Object, _setter.Object, _provider.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_get_file_configuration()
|
||||
{
|
||||
var expected = new Responses.OkResponse<FileConfiguration>(new FileConfiguration());
|
||||
|
||||
this.Given(x => x.GivenTheGetConfigurationReturns(expected))
|
||||
.When(x => x.WhenIGetTheFileConfiguration())
|
||||
.Then(x => x.TheTheGetFileConfigurationIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_when_cannot_get_config()
|
||||
{
|
||||
[Fact]
|
||||
public void should_get_file_configuration()
|
||||
{
|
||||
var expected = new Responses.OkResponse<FileConfiguration>(new FileConfiguration());
|
||||
|
||||
this.Given(x => x.GivenTheGetConfigurationReturns(expected))
|
||||
.When(x => x.WhenIGetTheFileConfiguration())
|
||||
.Then(x => x.TheTheGetFileConfigurationIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_when_cannot_get_config()
|
||||
{
|
||||
var expected = new Responses.ErrorResponse<FileConfiguration>(It.IsAny<Error>());
|
||||
|
||||
this.Given(x => x.GivenTheGetConfigurationReturns(expected))
|
||||
.When(x => x.WhenIGetTheFileConfiguration())
|
||||
.Then(x => x.TheTheGetFileConfigurationIsCalledCorrectly())
|
||||
.And(x => x.ThenTheResponseIs<BadRequestObjectResult>())
|
||||
.BDDfy();
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_post_file_configuration()
|
||||
{
|
||||
var expected = new FileConfiguration();
|
||||
|
||||
this.Given(x => GivenTheFileConfiguration(expected))
|
||||
.And(x => GivenTheConfigSetterReturns(new OkResponse()))
|
||||
.When(x => WhenIPostTheFileConfiguration())
|
||||
.Then(x => x.ThenTheConfigrationSetterIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_when_cannot_set_config()
|
||||
{
|
||||
var expected = new FileConfiguration();
|
||||
|
||||
this.Given(x => GivenTheFileConfiguration(expected))
|
||||
.And(x => GivenTheConfigSetterReturns(new ErrorResponse(new FakeError())))
|
||||
.When(x => WhenIPostTheFileConfiguration())
|
||||
.Then(x => x.ThenTheConfigrationSetterIsCalledCorrectly())
|
||||
.And(x => ThenTheResponseIs<BadRequestObjectResult>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheConfigSetterReturns(Response response)
|
||||
{
|
||||
_setter
|
||||
.Setup(x => x.Set(It.IsAny<FileConfiguration>()))
|
||||
.ReturnsAsync(response);
|
||||
}
|
||||
|
||||
private void ThenTheConfigrationSetterIsCalledCorrectly()
|
||||
{
|
||||
_setter
|
||||
.Verify(x => x.Set(_fileConfiguration), Times.Once);
|
||||
}
|
||||
|
||||
private void WhenIPostTheFileConfiguration()
|
||||
{
|
||||
_result = _controller.Post(_fileConfiguration).Result;
|
||||
}
|
||||
|
||||
private void GivenTheFileConfiguration(FileConfiguration fileConfiguration)
|
||||
{
|
||||
_fileConfiguration = fileConfiguration;
|
||||
}
|
||||
|
||||
private void ThenTheResponseIs<T>()
|
||||
[Fact]
|
||||
public void should_post_file_configuration()
|
||||
{
|
||||
_result.ShouldBeOfType<T>();
|
||||
}
|
||||
|
||||
private void GivenTheGetConfigurationReturns(Ocelot.Responses.Response<FileConfiguration> fileConfiguration)
|
||||
{
|
||||
_repo
|
||||
.Setup(x => x.Get())
|
||||
.ReturnsAsync(fileConfiguration);
|
||||
}
|
||||
|
||||
private void WhenIGetTheFileConfiguration()
|
||||
{
|
||||
_result = _controller.Get().Result;
|
||||
}
|
||||
|
||||
private void TheTheGetFileConfigurationIsCalledCorrectly()
|
||||
var expected = new FileConfiguration();
|
||||
|
||||
this.Given(x => GivenTheFileConfiguration(expected))
|
||||
.And(x => GivenTheConfigSetterReturns(new OkResponse()))
|
||||
.When(x => WhenIPostTheFileConfiguration())
|
||||
.Then(x => x.ThenTheConfigrationSetterIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_when_cannot_set_config()
|
||||
{
|
||||
var expected = new FileConfiguration();
|
||||
|
||||
this.Given(x => GivenTheFileConfiguration(expected))
|
||||
.And(x => GivenTheConfigSetterReturns(new ErrorResponse(new FakeError())))
|
||||
.When(x => WhenIPostTheFileConfiguration())
|
||||
.Then(x => x.ThenTheConfigrationSetterIsCalledCorrectly())
|
||||
.And(x => ThenTheResponseIs<BadRequestObjectResult>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheConfigSetterReturns(Response response)
|
||||
{
|
||||
_setter
|
||||
.Setup(x => x.Set(It.IsAny<FileConfiguration>()))
|
||||
.ReturnsAsync(response);
|
||||
}
|
||||
|
||||
private void ThenTheConfigrationSetterIsCalledCorrectly()
|
||||
{
|
||||
_setter
|
||||
.Verify(x => x.Set(_fileConfiguration), Times.Once);
|
||||
}
|
||||
|
||||
private void WhenIPostTheFileConfiguration()
|
||||
{
|
||||
_result = _controller.Post(_fileConfiguration).Result;
|
||||
}
|
||||
|
||||
private void GivenTheFileConfiguration(FileConfiguration fileConfiguration)
|
||||
{
|
||||
_fileConfiguration = fileConfiguration;
|
||||
}
|
||||
|
||||
private void ThenTheResponseIs<T>()
|
||||
{
|
||||
_result.ShouldBeOfType<T>();
|
||||
}
|
||||
|
||||
private void GivenTheGetConfigurationReturns(Ocelot.Responses.Response<FileConfiguration> fileConfiguration)
|
||||
{
|
||||
_repo
|
||||
.Verify(x => x.Get(), Times.Once);
|
||||
}
|
||||
|
||||
private class FakeError : Error
|
||||
{
|
||||
public FakeError() : base(string.Empty, OcelotErrorCode.CannotAddDataError)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
.Setup(x => x.Get())
|
||||
.ReturnsAsync(fileConfiguration);
|
||||
}
|
||||
|
||||
private void WhenIGetTheFileConfiguration()
|
||||
{
|
||||
_result = _controller.Get().Result;
|
||||
}
|
||||
|
||||
private void TheTheGetFileConfigurationIsCalledCorrectly()
|
||||
{
|
||||
_repo
|
||||
.Verify(x => x.Get(), Times.Once);
|
||||
}
|
||||
|
||||
private class FakeError : Error
|
||||
{
|
||||
public FakeError() : base(string.Empty, OcelotErrorCode.CannotAddDataError, 404)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,404 +1,403 @@
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
namespace Ocelot.UnitTests.DependencyInjection
|
||||
{
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using Ocelot.Configuration.Setter;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Ocelot.Infrastructure;
|
||||
using Ocelot.Multiplexer;
|
||||
using Ocelot.Requester;
|
||||
using Ocelot.UnitTests.Requester;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.LoadBalancer.LoadBalancers;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using static Ocelot.UnitTests.Multiplexing.UserDefinedResponseAggregatorTests;
|
||||
|
||||
namespace Ocelot.UnitTests.DependencyInjection
|
||||
{
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using Ocelot.Configuration.Setter;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Ocelot.Infrastructure;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
using Ocelot.Requester;
|
||||
using Ocelot.UnitTests.Requester;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using static Ocelot.UnitTests.Middleware.UserDefinedResponseAggregatorTests;
|
||||
|
||||
public class OcelotBuilderTests
|
||||
{
|
||||
private readonly IServiceCollection _services;
|
||||
private IServiceProvider _serviceProvider;
|
||||
private readonly IConfiguration _configRoot;
|
||||
private IOcelotBuilder _ocelotBuilder;
|
||||
private readonly int _maxRetries;
|
||||
private Exception _ex;
|
||||
|
||||
public OcelotBuilderTests()
|
||||
{
|
||||
_configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
|
||||
_services = new ServiceCollection();
|
||||
_services.AddSingleton<IWebHostEnvironment>(GetHostingEnvironment());
|
||||
_services.AddSingleton(_configRoot);
|
||||
_maxRetries = 100;
|
||||
}
|
||||
|
||||
private IWebHostEnvironment GetHostingEnvironment()
|
||||
{
|
||||
var environment = new Mock<IWebHostEnvironment>();
|
||||
environment
|
||||
.Setup(e => e.ApplicationName)
|
||||
.Returns(typeof(OcelotBuilderTests).GetTypeInfo().Assembly.GetName().Name);
|
||||
|
||||
return environment.Object;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_specific_delegating_handlers_transient()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandler>())
|
||||
.And(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => ThenTheSpecificHandlersAreTransient())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_type_specific_delegating_handlers_transient()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddTypeSpecificTransientDelegatingHandler(typeof(FakeDelegatingHandler)))
|
||||
.And(x => AddTypeSpecificTransientDelegatingHandler(typeof(FakeDelegatingHandlerTwo)))
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => ThenTheSpecificHandlersAreTransient())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_global_delegating_handlers_transient()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandler>())
|
||||
.And(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => ThenTheGlobalHandlersAreTransient())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_global_type_delegating_handlers_transient()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandler>())
|
||||
.And(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => ThenTheGlobalHandlersAreTransient())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_up_services()
|
||||
{
|
||||
this.When(x => WhenISetUpOcelotServices())
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_ocelot_builder()
|
||||
{
|
||||
this.When(x => WhenISetUpOcelotServices())
|
||||
.Then(x => ThenAnOcelotBuilderIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_use_logger_factory()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => WhenIValidateScopes())
|
||||
.When(x => WhenIAccessLoggerFactory())
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_up_without_passing_in_config()
|
||||
{
|
||||
this.When(x => WhenISetUpOcelotServicesWithoutConfig())
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_singleton_defined_aggregators()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddSingletonDefinedAggregator<TestDefinedAggregator>())
|
||||
.When(x => AddSingletonDefinedAggregator<TestDefinedAggregator>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TestDefinedAggregator, TestDefinedAggregator>())
|
||||
.And(x => ThenTheAggregatorsAreSingleton<TestDefinedAggregator, TestDefinedAggregator>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_transient_defined_aggregators()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddTransientDefinedAggregator<TestDefinedAggregator>())
|
||||
.When(x => AddTransientDefinedAggregator<TestDefinedAggregator>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TestDefinedAggregator, TestDefinedAggregator>())
|
||||
.And(x => ThenTheAggregatorsAreTransient<TestDefinedAggregator, TestDefinedAggregator>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_custom_load_balancer_creators_by_default_ctor()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => _ocelotBuilder.AddCustomLoadBalancer<FakeCustomLoadBalancer>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_custom_load_balancer_creators_by_factory_method()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => _ocelotBuilder.AddCustomLoadBalancer(() => new FakeCustomLoadBalancer()))
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_custom_load_balancer_creators_by_di_factory_method()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => _ocelotBuilder.AddCustomLoadBalancer(provider => new FakeCustomLoadBalancer()))
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_custom_load_balancer_creators_by_factory_method_with_arguments()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => _ocelotBuilder.AddCustomLoadBalancer((reroute, discoveryProvider) => new FakeCustomLoadBalancer()))
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_replace_iplaceholder()
|
||||
{
|
||||
this.Given(x => x.WhenISetUpOcelotServices())
|
||||
.When(x => AddConfigPlaceholders())
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.And(x => ThenTheIPlaceholderInstanceIsReplaced())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_custom_load_balancer_creators()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => _ocelotBuilder.AddCustomLoadBalancer((provider, reroute, discoveryProvider) => new FakeCustomLoadBalancer()))
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void AddSingletonDefinedAggregator<T>()
|
||||
where T : class, IDefinedAggregator
|
||||
{
|
||||
_ocelotBuilder.AddSingletonDefinedAggregator<T>();
|
||||
}
|
||||
|
||||
private void AddTransientDefinedAggregator<T>()
|
||||
where T : class, IDefinedAggregator
|
||||
{
|
||||
_ocelotBuilder.AddTransientDefinedAggregator<T>();
|
||||
}
|
||||
|
||||
private void AddConfigPlaceholders()
|
||||
{
|
||||
_ocelotBuilder.AddConfigPlaceholders();
|
||||
}
|
||||
|
||||
private void ThenTheSpecificHandlersAreTransient()
|
||||
{
|
||||
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||
var first = handlers[0];
|
||||
handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||
var second = handlers[0];
|
||||
first.ShouldNotBe(second);
|
||||
}
|
||||
|
||||
private void ThenTheGlobalHandlersAreTransient()
|
||||
{
|
||||
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||
var first = handlers[0].DelegatingHandler;
|
||||
handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||
var second = handlers[0].DelegatingHandler;
|
||||
first.ShouldNotBe(second);
|
||||
}
|
||||
|
||||
private void AddTransientGlobalDelegatingHandler<T>()
|
||||
where T : DelegatingHandler
|
||||
{
|
||||
_ocelotBuilder.AddDelegatingHandler<T>(true);
|
||||
}
|
||||
|
||||
private void AddSpecificTransientDelegatingHandler<T>()
|
||||
where T : DelegatingHandler
|
||||
{
|
||||
_ocelotBuilder.AddDelegatingHandler<T>();
|
||||
}
|
||||
|
||||
private void AddTypeTransientGlobalDelegatingHandler(Type type)
|
||||
{
|
||||
_ocelotBuilder.AddDelegatingHandler(type, true);
|
||||
}
|
||||
|
||||
private void AddTypeSpecificTransientDelegatingHandler(Type type)
|
||||
{
|
||||
_ocelotBuilder.AddDelegatingHandler(type);
|
||||
}
|
||||
|
||||
private void ThenTheProviderIsRegisteredAndReturnsHandlers<TOne, TWo>()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||
handlers[0].DelegatingHandler.ShouldBeOfType<TOne>();
|
||||
handlers[1].DelegatingHandler.ShouldBeOfType<TWo>();
|
||||
}
|
||||
|
||||
private void ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<TOne, TWo>()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||
handlers[0].ShouldBeOfType<TOne>();
|
||||
handlers[1].ShouldBeOfType<TWo>();
|
||||
}
|
||||
|
||||
private void ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TOne, TWo>()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var handlers = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
|
||||
handlers[0].ShouldBeOfType<TOne>();
|
||||
handlers[1].ShouldBeOfType<TWo>();
|
||||
}
|
||||
|
||||
private void ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var creators = _serviceProvider.GetServices<ILoadBalancerCreator>().ToList();
|
||||
creators.Count(c => c.GetType() == typeof(NoLoadBalancerCreator)).ShouldBe(1);
|
||||
creators.Count(c => c.GetType() == typeof(RoundRobinCreator)).ShouldBe(1);
|
||||
creators.Count(c => c.GetType() == typeof(CookieStickySessionsCreator)).ShouldBe(1);
|
||||
creators.Count(c => c.GetType() == typeof(LeastConnectionCreator)).ShouldBe(1);
|
||||
creators.Count(c => c.GetType() == typeof(DelegateInvokingLoadBalancerCreator<FakeCustomLoadBalancer>)).ShouldBe(1);
|
||||
}
|
||||
|
||||
private void ThenTheAggregatorsAreTransient<TOne, TWo>()
|
||||
{
|
||||
var aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
|
||||
var first = aggregators[0];
|
||||
aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
|
||||
var second = aggregators[0];
|
||||
first.ShouldNotBe(second);
|
||||
}
|
||||
|
||||
private void ThenTheAggregatorsAreSingleton<TOne, TWo>()
|
||||
{
|
||||
var aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
|
||||
var first = aggregators[0];
|
||||
aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
|
||||
var second = aggregators[0];
|
||||
first.ShouldBe(second);
|
||||
}
|
||||
|
||||
private void ThenAnOcelotBuilderIsReturned()
|
||||
{
|
||||
_ocelotBuilder.ShouldBeOfType<OcelotBuilder>();
|
||||
}
|
||||
|
||||
private void ThenTheIPlaceholderInstanceIsReplaced()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var placeholders = _serviceProvider.GetService<IPlaceholders>();
|
||||
placeholders.ShouldBeOfType<ConfigAwarePlaceholders>();
|
||||
}
|
||||
|
||||
private void WhenISetUpOcelotServices()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ocelotBuilder = _services.AddOcelot(_configRoot);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void WhenISetUpOcelotServicesWithoutConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ocelotBuilder = _services.AddOcelot();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void WhenIAccessLoggerFactory()
|
||||
{
|
||||
try
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var logger = _serviceProvider.GetService<IFileConfigurationSetter>();
|
||||
logger.ShouldNotBeNull();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void WhenIValidateScopes()
|
||||
{
|
||||
try
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider(new ServiceProviderOptions { ValidateScopes = true });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void ThenAnExceptionIsntThrown()
|
||||
{
|
||||
_ex.ShouldBeNull();
|
||||
}
|
||||
|
||||
private class FakeCustomLoadBalancer : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease(DownstreamContext context)
|
||||
{
|
||||
// Not relevant for these tests
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Release(ServiceHostAndPort hostAndPort)
|
||||
{
|
||||
// Not relevant for these tests
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public class OcelotBuilderTests
|
||||
{
|
||||
private readonly IServiceCollection _services;
|
||||
private IServiceProvider _serviceProvider;
|
||||
private readonly IConfiguration _configRoot;
|
||||
private IOcelotBuilder _ocelotBuilder;
|
||||
private readonly int _maxRetries;
|
||||
private Exception _ex;
|
||||
|
||||
public OcelotBuilderTests()
|
||||
{
|
||||
_configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
|
||||
_services = new ServiceCollection();
|
||||
_services.AddSingleton<IWebHostEnvironment>(GetHostingEnvironment());
|
||||
_services.AddSingleton(_configRoot);
|
||||
_maxRetries = 100;
|
||||
}
|
||||
|
||||
private IWebHostEnvironment GetHostingEnvironment()
|
||||
{
|
||||
var environment = new Mock<IWebHostEnvironment>();
|
||||
environment
|
||||
.Setup(e => e.ApplicationName)
|
||||
.Returns(typeof(OcelotBuilderTests).GetTypeInfo().Assembly.GetName().Name);
|
||||
|
||||
return environment.Object;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_specific_delegating_handlers_transient()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandler>())
|
||||
.And(x => AddSpecificTransientDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => ThenTheSpecificHandlersAreTransient())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_type_specific_delegating_handlers_transient()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddTypeSpecificTransientDelegatingHandler(typeof(FakeDelegatingHandler)))
|
||||
.And(x => AddTypeSpecificTransientDelegatingHandler(typeof(FakeDelegatingHandlerTwo)))
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => ThenTheSpecificHandlersAreTransient())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_global_delegating_handlers_transient()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandler>())
|
||||
.And(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => ThenTheGlobalHandlersAreTransient())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_global_type_delegating_handlers_transient()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandler>())
|
||||
.And(x => AddTransientGlobalDelegatingHandler<FakeDelegatingHandlerTwo>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||
.And(x => ThenTheGlobalHandlersAreTransient())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_up_services()
|
||||
{
|
||||
this.When(x => WhenISetUpOcelotServices())
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_ocelot_builder()
|
||||
{
|
||||
this.When(x => WhenISetUpOcelotServices())
|
||||
.Then(x => ThenAnOcelotBuilderIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_use_logger_factory()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => WhenIValidateScopes())
|
||||
.When(x => WhenIAccessLoggerFactory())
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_up_without_passing_in_config()
|
||||
{
|
||||
this.When(x => WhenISetUpOcelotServicesWithoutConfig())
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_singleton_defined_aggregators()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddSingletonDefinedAggregator<TestDefinedAggregator>())
|
||||
.When(x => AddSingletonDefinedAggregator<TestDefinedAggregator>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TestDefinedAggregator, TestDefinedAggregator>())
|
||||
.And(x => ThenTheAggregatorsAreSingleton<TestDefinedAggregator, TestDefinedAggregator>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_transient_defined_aggregators()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => AddTransientDefinedAggregator<TestDefinedAggregator>())
|
||||
.When(x => AddTransientDefinedAggregator<TestDefinedAggregator>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TestDefinedAggregator, TestDefinedAggregator>())
|
||||
.And(x => ThenTheAggregatorsAreTransient<TestDefinedAggregator, TestDefinedAggregator>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_custom_load_balancer_creators_by_default_ctor()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => _ocelotBuilder.AddCustomLoadBalancer<FakeCustomLoadBalancer>())
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_custom_load_balancer_creators_by_factory_method()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => _ocelotBuilder.AddCustomLoadBalancer(() => new FakeCustomLoadBalancer()))
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_custom_load_balancer_creators_by_di_factory_method()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => _ocelotBuilder.AddCustomLoadBalancer(provider => new FakeCustomLoadBalancer()))
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_custom_load_balancer_creators_by_factory_method_with_arguments()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => _ocelotBuilder.AddCustomLoadBalancer((reroute, discoveryProvider) => new FakeCustomLoadBalancer()))
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_replace_iplaceholder()
|
||||
{
|
||||
this.Given(x => x.WhenISetUpOcelotServices())
|
||||
.When(x => AddConfigPlaceholders())
|
||||
.Then(x => ThenAnExceptionIsntThrown())
|
||||
.And(x => ThenTheIPlaceholderInstanceIsReplaced())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_custom_load_balancer_creators()
|
||||
{
|
||||
this.Given(x => WhenISetUpOcelotServices())
|
||||
.When(x => _ocelotBuilder.AddCustomLoadBalancer((provider, reroute, discoveryProvider) => new FakeCustomLoadBalancer()))
|
||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void AddSingletonDefinedAggregator<T>()
|
||||
where T : class, IDefinedAggregator
|
||||
{
|
||||
_ocelotBuilder.AddSingletonDefinedAggregator<T>();
|
||||
}
|
||||
|
||||
private void AddTransientDefinedAggregator<T>()
|
||||
where T : class, IDefinedAggregator
|
||||
{
|
||||
_ocelotBuilder.AddTransientDefinedAggregator<T>();
|
||||
}
|
||||
|
||||
private void AddConfigPlaceholders()
|
||||
{
|
||||
_ocelotBuilder.AddConfigPlaceholders();
|
||||
}
|
||||
|
||||
private void ThenTheSpecificHandlersAreTransient()
|
||||
{
|
||||
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||
var first = handlers[0];
|
||||
handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||
var second = handlers[0];
|
||||
first.ShouldNotBe(second);
|
||||
}
|
||||
|
||||
private void ThenTheGlobalHandlersAreTransient()
|
||||
{
|
||||
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||
var first = handlers[0].DelegatingHandler;
|
||||
handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||
var second = handlers[0].DelegatingHandler;
|
||||
first.ShouldNotBe(second);
|
||||
}
|
||||
|
||||
private void AddTransientGlobalDelegatingHandler<T>()
|
||||
where T : DelegatingHandler
|
||||
{
|
||||
_ocelotBuilder.AddDelegatingHandler<T>(true);
|
||||
}
|
||||
|
||||
private void AddSpecificTransientDelegatingHandler<T>()
|
||||
where T : DelegatingHandler
|
||||
{
|
||||
_ocelotBuilder.AddDelegatingHandler<T>();
|
||||
}
|
||||
|
||||
private void AddTypeTransientGlobalDelegatingHandler(Type type)
|
||||
{
|
||||
_ocelotBuilder.AddDelegatingHandler(type, true);
|
||||
}
|
||||
|
||||
private void AddTypeSpecificTransientDelegatingHandler(Type type)
|
||||
{
|
||||
_ocelotBuilder.AddDelegatingHandler(type);
|
||||
}
|
||||
|
||||
private void ThenTheProviderIsRegisteredAndReturnsHandlers<TOne, TWo>()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var handlers = _serviceProvider.GetServices<GlobalDelegatingHandler>().ToList();
|
||||
handlers[0].DelegatingHandler.ShouldBeOfType<TOne>();
|
||||
handlers[1].DelegatingHandler.ShouldBeOfType<TWo>();
|
||||
}
|
||||
|
||||
private void ThenTheProviderIsRegisteredAndReturnsSpecificHandlers<TOne, TWo>()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||
handlers[0].ShouldBeOfType<TOne>();
|
||||
handlers[1].ShouldBeOfType<TWo>();
|
||||
}
|
||||
|
||||
private void ThenTheProviderIsRegisteredAndReturnsSpecificAggregators<TOne, TWo>()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var handlers = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
|
||||
handlers[0].ShouldBeOfType<TOne>();
|
||||
handlers[1].ShouldBeOfType<TWo>();
|
||||
}
|
||||
|
||||
private void ThenTheProviderIsRegisteredAndReturnsBothBuiltInAndCustomLoadBalancerCreators()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var creators = _serviceProvider.GetServices<ILoadBalancerCreator>().ToList();
|
||||
creators.Count(c => c.GetType() == typeof(NoLoadBalancerCreator)).ShouldBe(1);
|
||||
creators.Count(c => c.GetType() == typeof(RoundRobinCreator)).ShouldBe(1);
|
||||
creators.Count(c => c.GetType() == typeof(CookieStickySessionsCreator)).ShouldBe(1);
|
||||
creators.Count(c => c.GetType() == typeof(LeastConnectionCreator)).ShouldBe(1);
|
||||
creators.Count(c => c.GetType() == typeof(DelegateInvokingLoadBalancerCreator<FakeCustomLoadBalancer>)).ShouldBe(1);
|
||||
}
|
||||
|
||||
private void ThenTheAggregatorsAreTransient<TOne, TWo>()
|
||||
{
|
||||
var aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
|
||||
var first = aggregators[0];
|
||||
aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
|
||||
var second = aggregators[0];
|
||||
first.ShouldNotBe(second);
|
||||
}
|
||||
|
||||
private void ThenTheAggregatorsAreSingleton<TOne, TWo>()
|
||||
{
|
||||
var aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
|
||||
var first = aggregators[0];
|
||||
aggregators = _serviceProvider.GetServices<IDefinedAggregator>().ToList();
|
||||
var second = aggregators[0];
|
||||
first.ShouldBe(second);
|
||||
}
|
||||
|
||||
private void ThenAnOcelotBuilderIsReturned()
|
||||
{
|
||||
_ocelotBuilder.ShouldBeOfType<OcelotBuilder>();
|
||||
}
|
||||
|
||||
private void ThenTheIPlaceholderInstanceIsReplaced()
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var placeholders = _serviceProvider.GetService<IPlaceholders>();
|
||||
placeholders.ShouldBeOfType<ConfigAwarePlaceholders>();
|
||||
}
|
||||
|
||||
private void WhenISetUpOcelotServices()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ocelotBuilder = _services.AddOcelot(_configRoot);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void WhenISetUpOcelotServicesWithoutConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
_ocelotBuilder = _services.AddOcelot();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void WhenIAccessLoggerFactory()
|
||||
{
|
||||
try
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider();
|
||||
var logger = _serviceProvider.GetService<IFileConfigurationSetter>();
|
||||
logger.ShouldNotBeNull();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void WhenIValidateScopes()
|
||||
{
|
||||
try
|
||||
{
|
||||
_serviceProvider = _services.BuildServiceProvider(new ServiceProviderOptions { ValidateScopes = true });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_ex = e;
|
||||
}
|
||||
}
|
||||
|
||||
private void ThenAnExceptionIsntThrown()
|
||||
{
|
||||
_ex.ShouldBeNull();
|
||||
}
|
||||
|
||||
private class FakeCustomLoadBalancer : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext)
|
||||
{
|
||||
// Not relevant for these tests
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void Release(ServiceHostAndPort hostAndPort)
|
||||
{
|
||||
// Not relevant for these tests
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,101 +1,104 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.PathManipulation;
|
||||
using Ocelot.PathManipulation.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
namespace Ocelot.UnitTests.DownstreamPathManipulation
|
||||
{
|
||||
using Ocelot.DownstreamPathManipulation.Middleware;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.PathManipulation;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.DownstreamPathManipulation
|
||||
{
|
||||
public class ClaimsToDownstreamPathMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IChangeDownstreamPathTemplate> _changePath;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private ClaimsToDownstreamPathMiddleware _middleware;
|
||||
private DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
|
||||
public ClaimsToDownstreamPathMiddlewareTests()
|
||||
{
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ClaimsToDownstreamPathMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
public class ClaimsToDownstreamPathMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IChangeDownstreamPathTemplate> _changePath;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private ClaimsToDownstreamPathMiddleware _middleware;
|
||||
private RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public ClaimsToDownstreamPathMiddlewareTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ClaimsToDownstreamPathMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_changePath = new Mock<IChangeDownstreamPathTemplate>();
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com"));
|
||||
_middleware = new ClaimsToDownstreamPathMiddleware(_next, _loggerFactory.Object, _changePath.Object);
|
||||
}
|
||||
_httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com")));
|
||||
_middleware = new ClaimsToDownstreamPathMiddleware(_next, _loggerFactory.Object, _changePath.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_add_queries_correctly()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithClaimsToDownstreamPath(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("UserId", "Subject", "", 0),
|
||||
})
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => x.GivenTheChangeDownstreamPathReturnsOk())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenChangeDownstreamPathIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheChangeDownstreamPathReturnsOk()
|
||||
{
|
||||
_changePath
|
||||
.Setup(x => x.ChangeDownstreamPath(
|
||||
It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<IEnumerable<Claim>>(),
|
||||
It.IsAny<DownstreamPathTemplate>(),
|
||||
It.IsAny<List<PlaceholderNameAndValue>>()))
|
||||
.Returns(new OkResponse());
|
||||
}
|
||||
|
||||
private void ThenChangeDownstreamPathIsCalledCorrectly()
|
||||
{
|
||||
_changePath
|
||||
.Verify(x => x.ChangeDownstreamPath(
|
||||
It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<IEnumerable<Claim>>(),
|
||||
_httpContext.Items.DownstreamReRoute().DownstreamPathTemplate,
|
||||
_httpContext.Items.TemplatePlaceholderNameAndValues()), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_httpContext.Items.UpsertTemplatePlaceholderNameAndValues(downstreamRoute.TemplatePlaceholderNameAndValues);
|
||||
|
||||
[Fact]
|
||||
public void should_call_add_queries_correctly()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithClaimsToDownstreamPath(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("UserId", "Subject", "", 0),
|
||||
})
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => x.GivenTheChangeDownstreamPathReturnsOk())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenChangeDownstreamPathIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheChangeDownstreamPathReturnsOk()
|
||||
{
|
||||
_changePath
|
||||
.Setup(x => x.ChangeDownstreamPath(
|
||||
It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<IEnumerable<Claim>>(),
|
||||
It.IsAny<DownstreamPathTemplate>(),
|
||||
It.IsAny<List<PlaceholderNameAndValue>>()))
|
||||
.Returns(new OkResponse());
|
||||
}
|
||||
|
||||
private void ThenChangeDownstreamPathIsCalledCorrectly()
|
||||
{
|
||||
_changePath
|
||||
.Verify(x => x.ChangeDownstreamPath(
|
||||
It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<IEnumerable<Claim>>(),
|
||||
_downstreamContext.DownstreamReRoute.DownstreamPathTemplate,
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
|
||||
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
_httpContext.Items.UpsertDownstreamReRoute(downstreamRoute.ReRoute.DownstreamReRoute[0]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -11,11 +11,12 @@
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
using Ocelot.Multiplexer;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
@ -28,22 +29,20 @@
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly DownstreamRouteFinderMiddleware _middleware;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
private readonly Mock<IMultiplexer> _multiplexer;
|
||||
private RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public DownstreamRouteFinderMiddlewareTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_finder = new Mock<IDownstreamRouteProvider>();
|
||||
_factory = new Mock<IDownstreamRouteProviderFactory>();
|
||||
_factory.Setup(x => x.Get(It.IsAny<IInternalConfiguration>())).Returns(_finder.Object);
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<DownstreamRouteFinderMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_multiplexer = new Mock<IMultiplexer>();
|
||||
_middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _factory.Object, _multiplexer.Object);
|
||||
_middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _factory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -71,13 +70,13 @@
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetType();
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetType();
|
||||
}
|
||||
|
||||
private void GivenTheFollowingConfig(IInternalConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
_downstreamContext.Configuration = config;
|
||||
_httpContext.Items.SetIInternalConfiguration(config);
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteFinderReturns(DownstreamRoute downstreamRoute)
|
||||
@ -90,8 +89,8 @@
|
||||
|
||||
private void ThenTheScopedDataRepositoryIsCalledCorrectly()
|
||||
{
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues.ShouldBe(_downstreamRoute.Data.TemplatePlaceholderNameAndValues);
|
||||
_downstreamContext.Configuration.ServiceProviderConfiguration.ShouldBe(_config.ServiceProviderConfiguration);
|
||||
_httpContext.Items.TemplatePlaceholderNameAndValues().ShouldBe(_downstreamRoute.Data.TemplatePlaceholderNameAndValues);
|
||||
_httpContext.Items.IInternalConfiguration().ServiceProviderConfiguration.ShouldBe(_config.ServiceProviderConfiguration);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,436 +1,440 @@
|
||||
namespace Ocelot.UnitTests.DownstreamUrlCreator
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.DownstreamUrlCreator.Middleware;
|
||||
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
namespace Ocelot.UnitTests.DownstreamUrlCreator
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.DownstreamUrlCreator.Middleware;
|
||||
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class DownstreamUrlCreatorMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IDownstreamPathPlaceholderReplacer> _downstreamUrlTemplateVariableReplacer;
|
||||
private OkResponse<DownstreamPath> _downstreamPath;
|
||||
private readonly Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private DownstreamUrlCreatorMiddleware _middleware;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private readonly OcelotRequestDelegate _next;
|
||||
private readonly HttpRequestMessage _request;
|
||||
|
||||
public DownstreamUrlCreatorMiddlewareTests()
|
||||
{
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<DownstreamUrlCreatorMiddleware>()).Returns(_logger.Object);
|
||||
_downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamPathPlaceholderReplacer>();
|
||||
public class DownstreamUrlCreatorMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IDownstreamPathPlaceholderReplacer> _downstreamUrlTemplateVariableReplacer;
|
||||
private OkResponse<DownstreamPath> _downstreamPath;
|
||||
private readonly Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private DownstreamUrlCreatorMiddleware _middleware;
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly HttpRequestMessage _request;
|
||||
private HttpContext _httpContext;
|
||||
private Mock<IRequestScopedDataRepository> _repo;
|
||||
|
||||
public DownstreamUrlCreatorMiddlewareTests()
|
||||
{
|
||||
_repo = new Mock<IRequestScopedDataRepository>();
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<DownstreamUrlCreatorMiddleware>()).Returns(_logger.Object);
|
||||
_downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamPathPlaceholderReplacer>();
|
||||
_request = new HttpRequestMessage(HttpMethod.Get, "https://my.url/abc/?q=123");
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(_request);
|
||||
_next = context => Task.CompletedTask;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_replace_scheme_and_path()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithDownstreamScheme("https")
|
||||
.Build();
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||
new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://my.url/abc?q=123"))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://my.url:80/api/products/1?q=123"))
|
||||
.And(x => ThenTheQueryStringIs("?q=123"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_replace_query_string()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/api/units/{subscriptionId}/{unitId}/updates")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithDownstreamScheme("https")
|
||||
.Build();
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||
new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>
|
||||
{
|
||||
new PlaceholderNameAndValue("{subscriptionId}", "1"),
|
||||
new PlaceholderNameAndValue("{unitId}", "2")
|
||||
},
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:5000/api/subscriptions/1/updates?unitId=2"))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("api/units/1/2/updates"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://localhost:5000/api/units/1/2/updates"))
|
||||
.And(x => ThenTheQueryStringIs(""))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_replace_query_string_but_leave_non_placeholder_queries()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/api/units/{subscriptionId}/{unitId}/updates")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithDownstreamScheme("https")
|
||||
.Build();
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||
new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>
|
||||
{
|
||||
new PlaceholderNameAndValue("{subscriptionId}", "1"),
|
||||
new PlaceholderNameAndValue("{unitId}", "2")
|
||||
},
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:5000/api/subscriptions/1/updates?unitId=2&productId=2"))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("api/units/1/2/updates"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://localhost:5000/api/units/1/2/updates?productId=2"))
|
||||
.And(x => ThenTheQueryStringIs("?productId=2"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_replace_query_string_exact_match()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/api/units/{subscriptionId}/{unitId}/updates/{unitIdIty}")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithDownstreamScheme("https")
|
||||
.Build();
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||
new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>
|
||||
{
|
||||
new PlaceholderNameAndValue("{subscriptionId}", "1"),
|
||||
new PlaceholderNameAndValue("{unitId}", "2"),
|
||||
new PlaceholderNameAndValue("{unitIdIty}", "3")
|
||||
},
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:5000/api/subscriptions/1/updates?unitId=2?unitIdIty=3"))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("api/units/1/2/updates/3"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://localhost:5000/api/units/1/2/updates/3"))
|
||||
.And(x => ThenTheQueryStringIs(""))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_create_service_fabric_url()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithDownstreamScheme("https")
|
||||
.Build();
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.WithType("ServiceFabric")
|
||||
.WithHost("localhost")
|
||||
.WithPort(19081)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||
new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://my.url/abc?q=123"))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://my.url:80/api/products/1?q=123"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_service_fabric_url()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamScheme("http")
|
||||
.WithServiceName("Ocelot/OcelotApp")
|
||||
.WithUseServiceDiscovery(true)
|
||||
.Build();
|
||||
|
||||
var downstreamRoute = new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.Build());
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.WithType("ServiceFabric")
|
||||
.WithHost("localhost")
|
||||
.WithPort(19081)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:19081"))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturnSequence("/api/products/1", "Ocelot/OcelotApp"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:19081/Ocelot/OcelotApp/api/products/1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_service_fabric_url_with_query_string_for_stateless_service()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamScheme("http")
|
||||
.WithServiceName("Ocelot/OcelotApp")
|
||||
.WithUseServiceDiscovery(true)
|
||||
.Build();
|
||||
|
||||
var downstreamRoute = new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.Build());
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.WithType("ServiceFabric")
|
||||
.WithHost("localhost")
|
||||
.WithPort(19081)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:19081?Tom=test&laura=1"))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturnSequence("/api/products/1", "Ocelot/OcelotApp"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:19081/Ocelot/OcelotApp/api/products/1?Tom=test&laura=1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_service_fabric_url_with_query_string_for_stateful_service()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamScheme("http")
|
||||
.WithServiceName("Ocelot/OcelotApp")
|
||||
.WithUseServiceDiscovery(true)
|
||||
.Build();
|
||||
|
||||
var downstreamRoute = new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.Build());
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.WithType("ServiceFabric")
|
||||
.WithHost("localhost")
|
||||
.WithPort(19081)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:19081?PartitionKind=test&PartitionKey=1"))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturnSequence("/api/products/1", "Ocelot/OcelotApp"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:19081/Ocelot/OcelotApp/api/products/1?PartitionKind=test&PartitionKey=1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_service_fabric_url_with_version_from_upstream_path_template()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder().WithDownstreamReRoute(
|
||||
new DownstreamReRouteBuilder()
|
||||
.WithDownstreamScheme("http")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("/products").Build())
|
||||
.WithUseServiceDiscovery(true)
|
||||
.Build()
|
||||
).Build());
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.WithType("ServiceFabric")
|
||||
.WithHost("localhost")
|
||||
.WithPort(19081)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:19081?PartitionKind=test&PartitionKey=1"))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturnSequence("/products", "Service_1.0/Api"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:19081/Service_1.0/Api/products?PartitionKind=test&PartitionKey=1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void issue_473_should_not_remove_additional_query_string()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/Authorized/{action}?server={server}")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Post", "Get" })
|
||||
.WithDownstreamScheme("http")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("/uc/Authorized/{server}/{action}").Build())
|
||||
.Build();
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||
new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>
|
||||
{
|
||||
new PlaceholderNameAndValue("{action}", "1"),
|
||||
new PlaceholderNameAndValue("{server}", "2")
|
||||
},
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Post", "Get" })
|
||||
.Build())))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:5000/uc/Authorized/2/1/refresh?refreshToken=2288356cfb1338fdc5ff4ca558ec785118dfe1ff2864340937da8226863ff66d"))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("/Authorized/1?server=2"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:5000/Authorized/1?refreshToken=2288356cfb1338fdc5ff4ca558ec785118dfe1ff2864340937da8226863ff66d&server=2"))
|
||||
.And(x => ThenTheQueryStringIs("?refreshToken=2288356cfb1338fdc5ff4ca558ec785118dfe1ff2864340937da8226863ff66d&server=2"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_replace_by_empty_scheme()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamScheme("")
|
||||
.WithServiceName("Ocelot/OcelotApp")
|
||||
.WithUseServiceDiscovery(true)
|
||||
.Build();
|
||||
|
||||
var downstreamRoute = new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.Build());
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.WithType("ServiceFabric")
|
||||
.WithHost("localhost")
|
||||
.WithPort(19081)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("https://localhost:19081?PartitionKind=test&PartitionKey=1"))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturnSequence("/api/products/1", "Ocelot/OcelotApp"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://localhost:19081/Ocelot/OcelotApp/api/products/1?PartitionKind=test&PartitionKey=1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheServiceProviderConfigIs(ServiceProviderConfiguration config)
|
||||
{
|
||||
_next = context => Task.CompletedTask;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_replace_scheme_and_path()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithDownstreamScheme("https")
|
||||
.Build();
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||
new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://my.url/abc?q=123"))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://my.url:80/api/products/1?q=123"))
|
||||
.And(x => ThenTheQueryStringIs("?q=123"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_replace_query_string()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/api/units/{subscriptionId}/{unitId}/updates")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithDownstreamScheme("https")
|
||||
.Build();
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||
new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>
|
||||
{
|
||||
new PlaceholderNameAndValue("{subscriptionId}", "1"),
|
||||
new PlaceholderNameAndValue("{unitId}", "2")
|
||||
},
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:5000/api/subscriptions/1/updates?unitId=2"))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("api/units/1/2/updates"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://localhost:5000/api/units/1/2/updates"))
|
||||
.And(x => ThenTheQueryStringIs(""))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_replace_query_string_but_leave_non_placeholder_queries()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/api/units/{subscriptionId}/{unitId}/updates")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithDownstreamScheme("https")
|
||||
.Build();
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||
new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>
|
||||
{
|
||||
new PlaceholderNameAndValue("{subscriptionId}", "1"),
|
||||
new PlaceholderNameAndValue("{unitId}", "2")
|
||||
},
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:5000/api/subscriptions/1/updates?unitId=2&productId=2"))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("api/units/1/2/updates"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://localhost:5000/api/units/1/2/updates?productId=2"))
|
||||
.And(x => ThenTheQueryStringIs("?productId=2"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_replace_query_string_exact_match()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/api/units/{subscriptionId}/{unitId}/updates/{unitIdIty}")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithDownstreamScheme("https")
|
||||
.Build();
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||
new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>
|
||||
{
|
||||
new PlaceholderNameAndValue("{subscriptionId}", "1"),
|
||||
new PlaceholderNameAndValue("{unitId}", "2"),
|
||||
new PlaceholderNameAndValue("{unitIdIty}", "3")
|
||||
},
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:5000/api/subscriptions/1/updates?unitId=2?unitIdIty=3"))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("api/units/1/2/updates/3"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://localhost:5000/api/units/1/2/updates/3"))
|
||||
.And(x => ThenTheQueryStringIs(""))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_create_service_fabric_url()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithDownstreamScheme("https")
|
||||
.Build();
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.WithType("ServiceFabric")
|
||||
.WithHost("localhost")
|
||||
.WithPort(19081)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||
new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://my.url/abc?q=123"))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://my.url:80/api/products/1?q=123"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_service_fabric_url()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamScheme("http")
|
||||
.WithServiceName("Ocelot/OcelotApp")
|
||||
.WithUseServiceDiscovery(true)
|
||||
.Build();
|
||||
|
||||
var downstreamRoute = new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.Build());
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.WithType("ServiceFabric")
|
||||
.WithHost("localhost")
|
||||
.WithPort(19081)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:19081"))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturnSequence("/api/products/1", "Ocelot/OcelotApp"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:19081/Ocelot/OcelotApp/api/products/1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_service_fabric_url_with_query_string_for_stateless_service()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamScheme("http")
|
||||
.WithServiceName("Ocelot/OcelotApp")
|
||||
.WithUseServiceDiscovery(true)
|
||||
.Build();
|
||||
|
||||
var downstreamRoute = new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.Build());
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.WithType("ServiceFabric")
|
||||
.WithHost("localhost")
|
||||
.WithPort(19081)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:19081?Tom=test&laura=1"))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturnSequence("/api/products/1", "Ocelot/OcelotApp"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:19081/Ocelot/OcelotApp/api/products/1?Tom=test&laura=1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_service_fabric_url_with_query_string_for_stateful_service()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamScheme("http")
|
||||
.WithServiceName("Ocelot/OcelotApp")
|
||||
.WithUseServiceDiscovery(true)
|
||||
.Build();
|
||||
|
||||
var downstreamRoute = new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.Build());
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.WithType("ServiceFabric")
|
||||
.WithHost("localhost")
|
||||
.WithPort(19081)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:19081?PartitionKind=test&PartitionKey=1"))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturnSequence("/api/products/1", "Ocelot/OcelotApp"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:19081/Ocelot/OcelotApp/api/products/1?PartitionKind=test&PartitionKey=1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_create_service_fabric_url_with_version_from_upstream_path_template()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder().WithDownstreamReRoute(
|
||||
new DownstreamReRouteBuilder()
|
||||
.WithDownstreamScheme("http")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("/products").Build())
|
||||
.WithUseServiceDiscovery(true)
|
||||
.Build()
|
||||
).Build());
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.WithType("ServiceFabric")
|
||||
.WithHost("localhost")
|
||||
.WithPort(19081)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:19081?PartitionKind=test&PartitionKey=1"))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturnSequence("/products", "Service_1.0/Api"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:19081/Service_1.0/Api/products?PartitionKind=test&PartitionKey=1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void issue_473_should_not_remove_additional_query_string()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("/Authorized/{action}?server={server}")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Post", "Get" })
|
||||
.WithDownstreamScheme("http")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("/uc/Authorized/{server}/{action}").Build())
|
||||
.Build();
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(
|
||||
new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>
|
||||
{
|
||||
new PlaceholderNameAndValue("{action}", "1"),
|
||||
new PlaceholderNameAndValue("{server}", "2")
|
||||
},
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Post", "Get" })
|
||||
.Build())))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("http://localhost:5000/uc/Authorized/2/1/refresh?refreshToken=2288356cfb1338fdc5ff4ca558ec785118dfe1ff2864340937da8226863ff66d"))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturn("/Authorized/1?server=2"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("http://localhost:5000/Authorized/1?refreshToken=2288356cfb1338fdc5ff4ca558ec785118dfe1ff2864340937da8226863ff66d&server=2"))
|
||||
.And(x => ThenTheQueryStringIs("?refreshToken=2288356cfb1338fdc5ff4ca558ec785118dfe1ff2864340937da8226863ff66d&server=2"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_replace_by_empty_scheme()
|
||||
{
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithDownstreamScheme("")
|
||||
.WithServiceName("Ocelot/OcelotApp")
|
||||
.WithUseServiceDiscovery(true)
|
||||
.Build();
|
||||
|
||||
var downstreamRoute = new DownstreamRoute(
|
||||
new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.Build());
|
||||
|
||||
var config = new ServiceProviderConfigurationBuilder()
|
||||
.WithType("ServiceFabric")
|
||||
.WithHost("localhost")
|
||||
.WithPort(19081)
|
||||
.Build();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheServiceProviderConfigIs(config))
|
||||
.And(x => x.GivenTheDownstreamRequestUriIs("https://localhost:19081?PartitionKind=test&PartitionKey=1"))
|
||||
.And(x => x.GivenTheUrlReplacerWillReturnSequence("/api/products/1", "Ocelot/OcelotApp"))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamRequestUriIs("https://localhost:19081/Ocelot/OcelotApp/api/products/1?PartitionKind=test&PartitionKey=1"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheServiceProviderConfigIs(ServiceProviderConfiguration config)
|
||||
{
|
||||
var configuration = new InternalConfiguration(null, null, config, null, null, null, null, null, null);
|
||||
_downstreamContext.Configuration = configuration;
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
_httpContext.Items.SetIInternalConfiguration(configuration);
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware = new DownstreamUrlCreatorMiddleware(_next, _loggerFactory.Object, _downstreamUrlTemplateVariableReplacer.Object);
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_middleware = new DownstreamUrlCreatorMiddleware(_next, _loggerFactory.Object, _downstreamUrlTemplateVariableReplacer.Object);
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
_httpContext.Items.UpsertTemplatePlaceholderNameAndValues(downstreamRoute.TemplatePlaceholderNameAndValues);
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
|
||||
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRequestUriIs(string uri)
|
||||
{
|
||||
_httpContext.Items.UpsertDownstreamReRoute(downstreamRoute.ReRoute.DownstreamReRoute[0]);
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRequestUriIs(string uri)
|
||||
{
|
||||
_request.RequestUri = new Uri(uri);
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(_request);
|
||||
}
|
||||
|
||||
private void GivenTheUrlReplacerWillReturnSequence(params string[] paths)
|
||||
{
|
||||
var setup = _downstreamUrlTemplateVariableReplacer
|
||||
.SetupSequence(x => x.Replace(It.IsAny<string>(), It.IsAny<List<PlaceholderNameAndValue>>()));
|
||||
foreach (var path in paths)
|
||||
{
|
||||
var response = new OkResponse<DownstreamPath>(new DownstreamPath(path));
|
||||
setup.Returns(response);
|
||||
}
|
||||
}
|
||||
|
||||
private void GivenTheUrlReplacerWillReturn(string path)
|
||||
{
|
||||
_downstreamPath = new OkResponse<DownstreamPath>(new DownstreamPath(path));
|
||||
_downstreamUrlTemplateVariableReplacer
|
||||
.Setup(x => x.Replace(It.IsAny<string>(), It.IsAny<List<PlaceholderNameAndValue>>()))
|
||||
.Returns(_downstreamPath);
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamRequestUriIs(string expectedUri)
|
||||
{
|
||||
_downstreamContext.DownstreamRequest.ToHttpRequestMessage().RequestUri.OriginalString.ShouldBe(expectedUri);
|
||||
}
|
||||
|
||||
private void ThenTheQueryStringIs(string queryString)
|
||||
{
|
||||
_downstreamContext.DownstreamRequest.Query.ShouldBe(queryString);
|
||||
}
|
||||
}
|
||||
}
|
||||
_httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(_request));
|
||||
}
|
||||
|
||||
private void GivenTheUrlReplacerWillReturnSequence(params string[] paths)
|
||||
{
|
||||
var setup = _downstreamUrlTemplateVariableReplacer
|
||||
.SetupSequence(x => x.Replace(It.IsAny<string>(), It.IsAny<List<PlaceholderNameAndValue>>()));
|
||||
foreach (var path in paths)
|
||||
{
|
||||
var response = new OkResponse<DownstreamPath>(new DownstreamPath(path));
|
||||
setup.Returns(response);
|
||||
}
|
||||
}
|
||||
|
||||
private void GivenTheUrlReplacerWillReturn(string path)
|
||||
{
|
||||
_downstreamPath = new OkResponse<DownstreamPath>(new DownstreamPath(path));
|
||||
_downstreamUrlTemplateVariableReplacer
|
||||
.Setup(x => x.Replace(It.IsAny<string>(), It.IsAny<List<PlaceholderNameAndValue>>()))
|
||||
.Returns(_downstreamPath);
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamRequestUriIs(string expectedUri)
|
||||
{
|
||||
_httpContext.Items.DownstreamRequest().ToHttpRequestMessage().RequestUri.OriginalString.ShouldBe(expectedUri);
|
||||
}
|
||||
|
||||
private void ThenTheQueryStringIs(string queryString)
|
||||
{
|
||||
_httpContext.Items.DownstreamRequest().Query.ShouldBe(queryString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,13 @@ namespace Ocelot.UnitTests.Errors
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Repository;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Errors.Middleware;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
@ -19,19 +18,17 @@ namespace Ocelot.UnitTests.Errors
|
||||
public class ExceptionHandlerMiddlewareTests
|
||||
{
|
||||
private bool _shouldThrowAnException;
|
||||
private readonly Mock<IInternalConfigurationRepository> _configRepo;
|
||||
private readonly Mock<IRequestScopedDataRepository> _repo;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly ExceptionHandlerMiddleware _middleware;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
private RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public ExceptionHandlerMiddlewareTests()
|
||||
{
|
||||
_configRepo = new Mock<IInternalConfigurationRepository>();
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_repo = new Mock<IRequestScopedDataRepository>();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ExceptionHandlerMiddleware>()).Returns(_logger.Object);
|
||||
@ -44,9 +41,10 @@ namespace Ocelot.UnitTests.Errors
|
||||
throw new Exception("BOOM");
|
||||
}
|
||||
|
||||
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
|
||||
_httpContext.Response.StatusCode = (int)HttpStatusCode.OK;
|
||||
};
|
||||
_middleware = new ExceptionHandlerMiddleware(_next, _loggerFactory.Object, _configRepo.Object, _repo.Object);
|
||||
|
||||
_middleware = new ExceptionHandlerMiddleware(_next, _loggerFactory.Object, _repo.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -100,16 +98,6 @@ namespace Ocelot.UnitTests.Errors
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_throw_exception_if_config_provider_returns_error()
|
||||
{
|
||||
this.Given(_ => GivenAnExceptionWillNotBeThrownDownstream())
|
||||
.And(_ => GivenTheConfigReturnsError())
|
||||
.When(_ => WhenICallTheMiddlewareWithTheRequestIdKey("requestidkey", "1234"))
|
||||
.Then(_ => ThenAnExceptionIsThrown())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_throw_exception_if_config_provider_throws()
|
||||
{
|
||||
@ -122,32 +110,25 @@ namespace Ocelot.UnitTests.Errors
|
||||
|
||||
private void WhenICallTheMiddlewareWithTheRequestIdKey(string key, string value)
|
||||
{
|
||||
_downstreamContext.HttpContext.Request.Headers.Add(key, value);
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
_httpContext.Request.Headers.Add(key, value);
|
||||
//_httpContext.Setup(x => x.Request.Headers).Returns(new HeaderDictionary() { { key, value } });
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheConfigThrows()
|
||||
{
|
||||
var ex = new Exception("outer", new Exception("inner"));
|
||||
_configRepo
|
||||
.Setup(x => x.Get()).Throws(ex);
|
||||
// this will break when we handle not having the configuratio in the items dictionary
|
||||
_httpContext.Items = new Dictionary<object, object>();
|
||||
}
|
||||
|
||||
private void ThenAnExceptionIsThrown()
|
||||
{
|
||||
_downstreamContext.HttpContext.Response.StatusCode.ShouldBe(500);
|
||||
}
|
||||
|
||||
private void GivenTheConfigReturnsError()
|
||||
{
|
||||
var response = new Responses.ErrorResponse<IInternalConfiguration>(new FakeError());
|
||||
_configRepo
|
||||
.Setup(x => x.Get()).Returns(response);
|
||||
_httpContext.Response.StatusCode.ShouldBe(500);
|
||||
}
|
||||
|
||||
private void TheRequestIdIsSet(string key, string value)
|
||||
@ -157,9 +138,7 @@ namespace Ocelot.UnitTests.Errors
|
||||
|
||||
private void GivenTheConfigurationIs(IInternalConfiguration config)
|
||||
{
|
||||
var response = new Responses.OkResponse<IInternalConfiguration>(config);
|
||||
_configRepo
|
||||
.Setup(x => x.Get()).Returns(response);
|
||||
_httpContext.Items.Add("IInternalConfiguration", config);
|
||||
}
|
||||
|
||||
private void GivenAnExceptionWillNotBeThrownDownstream()
|
||||
@ -174,12 +153,12 @@ namespace Ocelot.UnitTests.Errors
|
||||
|
||||
private void ThenTheResponseIsOk()
|
||||
{
|
||||
_downstreamContext.HttpContext.Response.StatusCode.ShouldBe(200);
|
||||
_httpContext.Response.StatusCode.ShouldBe(200);
|
||||
}
|
||||
|
||||
private void ThenTheResponseIsError()
|
||||
{
|
||||
_downstreamContext.HttpContext.Response.StatusCode.ShouldBe(500);
|
||||
_httpContext.Response.StatusCode.ShouldBe(500);
|
||||
}
|
||||
|
||||
private void TheAspDotnetRequestIdIsSet()
|
||||
@ -190,7 +169,7 @@ namespace Ocelot.UnitTests.Errors
|
||||
private class FakeError : Error
|
||||
{
|
||||
internal FakeError()
|
||||
: base("meh", OcelotErrorCode.CannotAddDataError)
|
||||
: base("meh", OcelotErrorCode.CannotAddDataError, 404)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -1,59 +1,59 @@
|
||||
namespace Ocelot.UnitTests.Eureka
|
||||
{
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.DependencyInjection;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Middleware.Pipeline;
|
||||
using Steeltoe.Discovery.Client;
|
||||
using Shouldly;
|
||||
using Steeltoe.Common.Discovery;
|
||||
using Steeltoe.Discovery.Eureka;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
//namespace Ocelot.UnitTests.Eureka
|
||||
//{
|
||||
// using Microsoft.Extensions.Configuration;
|
||||
// using Microsoft.Extensions.DependencyInjection;
|
||||
// using Ocelot.DependencyInjection;
|
||||
// using Ocelot.Middleware;
|
||||
// using Ocelot.Middleware.Pipeline;
|
||||
// using Steeltoe.Discovery.Client;
|
||||
// using Shouldly;
|
||||
// using Steeltoe.Common.Discovery;
|
||||
// using Steeltoe.Discovery.Eureka;
|
||||
// using TestStack.BDDfy;
|
||||
// using Xunit;
|
||||
|
||||
public class OcelotPipelineExtensionsTests
|
||||
{
|
||||
private OcelotPipelineBuilder _builder;
|
||||
private OcelotRequestDelegate _handlers;
|
||||
// public class OcelotPipelineExtensionsTests
|
||||
// {
|
||||
// private OcelotPipelineBuilder _builder;
|
||||
// private OcelotRequestDelegate _handlers;
|
||||
|
||||
[Fact]
|
||||
public void should_set_up_pipeline()
|
||||
{
|
||||
this.Given(_ => GivenTheDepedenciesAreSetUp())
|
||||
.When(_ => WhenIBuild())
|
||||
.Then(_ => ThenThePipelineIsBuilt())
|
||||
.BDDfy();
|
||||
}
|
||||
// [Fact]
|
||||
// public void should_set_up_pipeline()
|
||||
// {
|
||||
// this.Given(_ => GivenTheDepedenciesAreSetUp())
|
||||
// .When(_ => WhenIBuild())
|
||||
// .Then(_ => ThenThePipelineIsBuilt())
|
||||
// .BDDfy();
|
||||
// }
|
||||
|
||||
private void ThenThePipelineIsBuilt()
|
||||
{
|
||||
_handlers.ShouldNotBeNull();
|
||||
}
|
||||
// private void ThenThePipelineIsBuilt()
|
||||
// {
|
||||
// _handlers.ShouldNotBeNull();
|
||||
// }
|
||||
|
||||
private void WhenIBuild()
|
||||
{
|
||||
_handlers = _builder.BuildOcelotPipeline(new OcelotPipelineConfiguration());
|
||||
}
|
||||
// private void WhenIBuild()
|
||||
// {
|
||||
// _handlers = _builder.BuildOcelotPipeline(new OcelotPipelineConfiguration());
|
||||
// }
|
||||
|
||||
private void GivenTheDepedenciesAreSetUp()
|
||||
{
|
||||
IConfigurationBuilder test = new ConfigurationBuilder();
|
||||
var root = test.Build();
|
||||
var services = new ServiceCollection();
|
||||
services.AddSingleton<IConfiguration>(root);
|
||||
services.AddDiscoveryClient(new DiscoveryOptions
|
||||
{
|
||||
ClientType = DiscoveryClientType.EUREKA,
|
||||
ClientOptions = new EurekaClientOptions()
|
||||
{
|
||||
ShouldFetchRegistry = false,
|
||||
ShouldRegisterWithEureka = false
|
||||
}
|
||||
});
|
||||
services.AddOcelot();
|
||||
var provider = services.BuildServiceProvider();
|
||||
_builder = new OcelotPipelineBuilder(provider);
|
||||
}
|
||||
}
|
||||
}
|
||||
// private void GivenTheDepedenciesAreSetUp()
|
||||
// {
|
||||
// IConfigurationBuilder test = new ConfigurationBuilder();
|
||||
// var root = test.Build();
|
||||
// var services = new ServiceCollection();
|
||||
// services.AddSingleton<IConfiguration>(root);
|
||||
// services.AddDiscoveryClient(new DiscoveryOptions
|
||||
// {
|
||||
// ClientType = DiscoveryClientType.EUREKA,
|
||||
// ClientOptions = new EurekaClientOptions()
|
||||
// {
|
||||
// ShouldFetchRegistry = false,
|
||||
// ShouldRegisterWithEureka = false
|
||||
// }
|
||||
// });
|
||||
// services.AddOcelot();
|
||||
// var provider = services.BuildServiceProvider();
|
||||
// _builder = new OcelotPipelineBuilder(provider);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
@ -150,7 +150,7 @@ namespace Ocelot.UnitTests.Headers
|
||||
private class AnyError : Error
|
||||
{
|
||||
public AnyError()
|
||||
: base("blahh", OcelotErrorCode.UnknownError)
|
||||
: base("blahh", OcelotErrorCode.UnknownError, 404)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,16 @@
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.Headers
|
||||
namespace Ocelot.UnitTests.Headers
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Headers;
|
||||
using Ocelot.Headers.Middleware;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using System.Collections.Generic;
|
||||
@ -26,19 +26,19 @@ namespace Ocelot.UnitTests.Headers
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private ClaimsToHeadersMiddleware _middleware;
|
||||
private DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
private RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public ClaimsToHeadersMiddlewareTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_addHeaders = new Mock<IAddHeadersToRequest>();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ClaimsToHeadersMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new ClaimsToHeadersMiddleware(_next, _loggerFactory.Object, _addHeaders.Object);
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com"));
|
||||
_httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -66,14 +66,16 @@ namespace Ocelot.UnitTests.Headers
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
|
||||
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
|
||||
|
||||
_httpContext.Items.UpsertTemplatePlaceholderNameAndValues(downstreamRoute.TemplatePlaceholderNameAndValues);
|
||||
|
||||
_httpContext.Items.UpsertDownstreamReRoute(downstreamRoute.ReRoute.DownstreamReRoute[0]);
|
||||
}
|
||||
|
||||
private void GivenTheAddHeadersToDownstreamRequestReturnsOk()
|
||||
@ -92,7 +94,7 @@ namespace Ocelot.UnitTests.Headers
|
||||
.Verify(x => x.SetHeadersOnDownstreamRequest(
|
||||
It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<IEnumerable<System.Security.Claims.Claim>>(),
|
||||
_downstreamContext.DownstreamRequest), Times.Once);
|
||||
_httpContext.Items.DownstreamRequest()), Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,119 +1,121 @@
|
||||
namespace Ocelot.UnitTests.Headers
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Authorisation.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.Headers;
|
||||
using Ocelot.Headers.Middleware;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class HttpHeadersTransformationMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IHttpContextRequestHeaderReplacer> _preReplacer;
|
||||
private readonly Mock<IHttpResponseHeaderReplacer> _postReplacer;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly HttpHeadersTransformationMiddleware _middleware;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
private readonly Mock<IAddHeadersToResponse> _addHeadersToResponse;
|
||||
private readonly Mock<IAddHeadersToRequest> _addHeadersToRequest;
|
||||
|
||||
public HttpHeadersTransformationMiddlewareTests()
|
||||
{
|
||||
_preReplacer = new Mock<IHttpContextRequestHeaderReplacer>();
|
||||
_postReplacer = new Mock<IHttpResponseHeaderReplacer>();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_addHeadersToResponse = new Mock<IAddHeadersToResponse>();
|
||||
_addHeadersToRequest = new Mock<IAddHeadersToRequest>();
|
||||
_middleware = new HttpHeadersTransformationMiddleware(
|
||||
_next, _loggerFactory.Object, _preReplacer.Object,
|
||||
_postReplacer.Object, _addHeadersToResponse.Object, _addHeadersToRequest.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_pre_and_post_header_transforms()
|
||||
{
|
||||
this.Given(x => GivenTheFollowingRequest())
|
||||
.And(x => GivenTheDownstreamRequestIs())
|
||||
.And(x => GivenTheReRouteHasPreFindAndReplaceSetUp())
|
||||
.And(x => GivenTheHttpResponseMessageIs())
|
||||
.When(x => WhenICallTheMiddleware())
|
||||
.Then(x => ThenTheIHttpContextRequestHeaderReplacerIsCalledCorrectly())
|
||||
.Then(x => ThenAddHeadersToRequestIsCalledCorrectly())
|
||||
.And(x => ThenTheIHttpResponseHeaderReplacerIsCalledCorrectly())
|
||||
.And(x => ThenAddHeadersToResponseIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenAddHeadersToResponseIsCalledCorrectly()
|
||||
{
|
||||
_addHeadersToResponse
|
||||
.Verify(x => x.Add(_downstreamContext.DownstreamReRoute.AddHeadersToDownstream, _downstreamContext.DownstreamResponse), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenAddHeadersToRequestIsCalledCorrectly()
|
||||
{
|
||||
_addHeadersToRequest
|
||||
.Verify(x => x.SetHeadersOnDownstreamRequest(_downstreamContext.DownstreamReRoute.AddHeadersToUpstream, _downstreamContext.HttpContext), Times.Once);
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRequestIs()
|
||||
{
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com"));
|
||||
}
|
||||
|
||||
private void GivenTheHttpResponseMessageIs()
|
||||
{
|
||||
_downstreamContext.DownstreamResponse = new DownstreamResponse(new HttpResponseMessage());
|
||||
}
|
||||
|
||||
private void GivenTheReRouteHasPreFindAndReplaceSetUp()
|
||||
{
|
||||
var fAndRs = new List<HeaderFindAndReplace>();
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder().WithUpstreamHeaderFindAndReplace(fAndRs)
|
||||
.WithDownstreamHeaderFindAndReplace(fAndRs).Build())
|
||||
.Build();
|
||||
|
||||
var dR = new DownstreamRoute(null, reRoute);
|
||||
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues = dR.TemplatePlaceholderNameAndValues;
|
||||
_downstreamContext.DownstreamReRoute = dR.ReRoute.DownstreamReRoute[0];
|
||||
}
|
||||
|
||||
private void ThenTheIHttpContextRequestHeaderReplacerIsCalledCorrectly()
|
||||
{
|
||||
_preReplacer.Verify(x => x.Replace(It.IsAny<HttpContext>(), It.IsAny<List<HeaderFindAndReplace>>()), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheIHttpResponseHeaderReplacerIsCalledCorrectly()
|
||||
{
|
||||
_postReplacer.Verify(x => x.Replace(It.IsAny<DownstreamContext>(), It.IsAny<List<HeaderFindAndReplace>>()), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheFollowingRequest()
|
||||
{
|
||||
_downstreamContext.HttpContext.Request.Headers.Add("test", "test");
|
||||
}
|
||||
}
|
||||
namespace Ocelot.UnitTests.Headers
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Authorisation.Middleware;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.Headers;
|
||||
using Ocelot.Headers.Middleware;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class HttpHeadersTransformationMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IHttpContextRequestHeaderReplacer> _preReplacer;
|
||||
private readonly Mock<IHttpResponseHeaderReplacer> _postReplacer;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly HttpHeadersTransformationMiddleware _middleware;
|
||||
private RequestDelegate _next;
|
||||
private readonly Mock<IAddHeadersToResponse> _addHeadersToResponse;
|
||||
private readonly Mock<IAddHeadersToRequest> _addHeadersToRequest;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public HttpHeadersTransformationMiddlewareTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_preReplacer = new Mock<IHttpContextRequestHeaderReplacer>();
|
||||
_postReplacer = new Mock<IHttpResponseHeaderReplacer>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_addHeadersToResponse = new Mock<IAddHeadersToResponse>();
|
||||
_addHeadersToRequest = new Mock<IAddHeadersToRequest>();
|
||||
_middleware = new HttpHeadersTransformationMiddleware(
|
||||
_next, _loggerFactory.Object, _preReplacer.Object,
|
||||
_postReplacer.Object, _addHeadersToResponse.Object, _addHeadersToRequest.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_pre_and_post_header_transforms()
|
||||
{
|
||||
this.Given(x => GivenTheFollowingRequest())
|
||||
.And(x => GivenTheDownstreamRequestIs())
|
||||
.And(x => GivenTheReRouteHasPreFindAndReplaceSetUp())
|
||||
.And(x => GivenTheHttpResponseMessageIs())
|
||||
.When(x => WhenICallTheMiddleware())
|
||||
.Then(x => ThenTheIHttpContextRequestHeaderReplacerIsCalledCorrectly())
|
||||
.Then(x => ThenAddHeadersToRequestIsCalledCorrectly())
|
||||
.And(x => ThenTheIHttpResponseHeaderReplacerIsCalledCorrectly())
|
||||
.And(x => ThenAddHeadersToResponseIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenAddHeadersToResponseIsCalledCorrectly()
|
||||
{
|
||||
_addHeadersToResponse
|
||||
.Verify(x => x.Add(_httpContext.Items.DownstreamReRoute().AddHeadersToDownstream, _httpContext.Items.DownstreamResponse()), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenAddHeadersToRequestIsCalledCorrectly()
|
||||
{
|
||||
_addHeadersToRequest
|
||||
.Verify(x => x.SetHeadersOnDownstreamRequest(_httpContext.Items.DownstreamReRoute().AddHeadersToUpstream, _httpContext), Times.Once);
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRequestIs()
|
||||
{
|
||||
_httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com")));
|
||||
}
|
||||
|
||||
private void GivenTheHttpResponseMessageIs()
|
||||
{
|
||||
_httpContext.Items.UpsertDownstreamResponse(new DownstreamResponse(new HttpResponseMessage()));
|
||||
}
|
||||
|
||||
private void GivenTheReRouteHasPreFindAndReplaceSetUp()
|
||||
{
|
||||
var fAndRs = new List<HeaderFindAndReplace>();
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder().WithUpstreamHeaderFindAndReplace(fAndRs)
|
||||
.WithDownstreamHeaderFindAndReplace(fAndRs).Build())
|
||||
.Build();
|
||||
|
||||
var dR = new DownstreamRoute(null, reRoute);
|
||||
|
||||
_httpContext.Items.UpsertTemplatePlaceholderNameAndValues(dR.TemplatePlaceholderNameAndValues);
|
||||
_httpContext.Items.UpsertDownstreamReRoute(dR.ReRoute.DownstreamReRoute[0]);
|
||||
}
|
||||
|
||||
private void ThenTheIHttpContextRequestHeaderReplacerIsCalledCorrectly()
|
||||
{
|
||||
_preReplacer.Verify(x => x.Replace(It.IsAny<HttpContext>(), It.IsAny<List<HeaderFindAndReplace>>()), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheIHttpResponseHeaderReplacerIsCalledCorrectly()
|
||||
{
|
||||
_postReplacer.Verify(x => x.Replace(It.IsAny<HttpContext>(), It.IsAny<List<HeaderFindAndReplace>>()), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheFollowingRequest()
|
||||
{
|
||||
_httpContext.Request.Headers.Add("test", "test");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ namespace Ocelot.UnitTests.Headers
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.Headers;
|
||||
using Ocelot.Infrastructure;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
@ -263,8 +264,11 @@ namespace Ocelot.UnitTests.Headers
|
||||
|
||||
private void WhenICallTheReplacer()
|
||||
{
|
||||
var context = new DownstreamContext(new DefaultHttpContext()) { DownstreamResponse = _response, DownstreamRequest = _request };
|
||||
_result = _replacer.Replace(context, _headerFindAndReplaces);
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Items.UpsertDownstreamResponse(_response);
|
||||
httpContext.Items.UpsertDownstreamRequest(_request);
|
||||
|
||||
_result = _replacer.Replace(httpContext, _headerFindAndReplaces);
|
||||
}
|
||||
|
||||
private void ThenTheHeaderShouldBe(string key, string value)
|
||||
|
@ -1,123 +1,123 @@
|
||||
using Moq;
|
||||
using Ocelot.Authorisation;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Infrastructure.Claims.Parser;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Infrastructure
|
||||
{
|
||||
public class ScopesAuthoriserTests
|
||||
{
|
||||
private ScopesAuthoriser _authoriser;
|
||||
public Mock<IClaimsParser> _parser;
|
||||
private ClaimsPrincipal _principal;
|
||||
private List<string> _allowedScopes;
|
||||
private Response<bool> _result;
|
||||
|
||||
public ScopesAuthoriserTests()
|
||||
{
|
||||
_parser = new Mock<IClaimsParser>();
|
||||
_authoriser = new ScopesAuthoriser(_parser.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_ok_if_no_allowed_scopes()
|
||||
{
|
||||
this.Given(_ => GivenTheFollowing(new ClaimsPrincipal()))
|
||||
.And(_ => GivenTheFollowing(new List<string>()))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new OkResponse<bool>(true)))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_ok_if_null_allowed_scopes()
|
||||
{
|
||||
this.Given(_ => GivenTheFollowing(new ClaimsPrincipal()))
|
||||
.And(_ => GivenTheFollowing((List<string>)null))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new OkResponse<bool>(true)))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_if_claims_parser_returns_error()
|
||||
{
|
||||
var fakeError = new FakeError();
|
||||
this.Given(_ => GivenTheFollowing(new ClaimsPrincipal()))
|
||||
.And(_ => GivenTheParserReturns(new ErrorResponse<List<string>>(fakeError)))
|
||||
.And(_ => GivenTheFollowing(new List<string>() { "doesntmatter" }))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new ErrorResponse<bool>(fakeError)))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_match_scopes_and_return_ok_result()
|
||||
{
|
||||
var claimsPrincipal = new ClaimsPrincipal();
|
||||
var allowedScopes = new List<string>() { "someScope" };
|
||||
|
||||
this.Given(_ => GivenTheFollowing(claimsPrincipal))
|
||||
.And(_ => GivenTheParserReturns(new OkResponse<List<string>>(allowedScopes)))
|
||||
.And(_ => GivenTheFollowing(allowedScopes))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new OkResponse<bool>(true)))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_match_scopes_and_return_error_result()
|
||||
{
|
||||
var fakeError = new FakeError();
|
||||
var claimsPrincipal = new ClaimsPrincipal();
|
||||
var allowedScopes = new List<string>() { "someScope" };
|
||||
var userScopes = new List<string>() { "anotherScope" };
|
||||
|
||||
this.Given(_ => GivenTheFollowing(claimsPrincipal))
|
||||
.And(_ => GivenTheParserReturns(new OkResponse<List<string>>(userScopes)))
|
||||
.And(_ => GivenTheFollowing(allowedScopes))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new ErrorResponse<bool>(fakeError)))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheParserReturns(Response<List<string>> response)
|
||||
{
|
||||
_parser.Setup(x => x.GetValuesByClaimType(It.IsAny<IEnumerable<Claim>>(), It.IsAny<string>())).Returns(response);
|
||||
}
|
||||
|
||||
private void GivenTheFollowing(ClaimsPrincipal principal)
|
||||
{
|
||||
_principal = principal;
|
||||
}
|
||||
|
||||
private void GivenTheFollowing(List<string> allowedScopes)
|
||||
{
|
||||
_allowedScopes = allowedScopes;
|
||||
}
|
||||
|
||||
private void WhenIAuthorise()
|
||||
{
|
||||
_result = _authoriser.Authorise(_principal, _allowedScopes);
|
||||
}
|
||||
|
||||
private void ThenTheFollowingIsReturned(Response<bool> expected)
|
||||
{
|
||||
_result.Data.ShouldBe(expected.Data);
|
||||
_result.IsError.ShouldBe(expected.IsError);
|
||||
}
|
||||
using Moq;
|
||||
using Ocelot.Authorisation;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Infrastructure.Claims.Parser;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Infrastructure
|
||||
{
|
||||
public class ScopesAuthoriserTests
|
||||
{
|
||||
private ScopesAuthoriser _authoriser;
|
||||
public Mock<IClaimsParser> _parser;
|
||||
private ClaimsPrincipal _principal;
|
||||
private List<string> _allowedScopes;
|
||||
private Response<bool> _result;
|
||||
|
||||
public ScopesAuthoriserTests()
|
||||
{
|
||||
_parser = new Mock<IClaimsParser>();
|
||||
_authoriser = new ScopesAuthoriser(_parser.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_ok_if_no_allowed_scopes()
|
||||
{
|
||||
this.Given(_ => GivenTheFollowing(new ClaimsPrincipal()))
|
||||
.And(_ => GivenTheFollowing(new List<string>()))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new OkResponse<bool>(true)))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_ok_if_null_allowed_scopes()
|
||||
{
|
||||
this.Given(_ => GivenTheFollowing(new ClaimsPrincipal()))
|
||||
.And(_ => GivenTheFollowing((List<string>)null))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new OkResponse<bool>(true)))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error_if_claims_parser_returns_error()
|
||||
{
|
||||
var fakeError = new FakeError();
|
||||
this.Given(_ => GivenTheFollowing(new ClaimsPrincipal()))
|
||||
.And(_ => GivenTheParserReturns(new ErrorResponse<List<string>>(fakeError)))
|
||||
.And(_ => GivenTheFollowing(new List<string>() { "doesntmatter" }))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new ErrorResponse<bool>(fakeError)))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_match_scopes_and_return_ok_result()
|
||||
{
|
||||
var claimsPrincipal = new ClaimsPrincipal();
|
||||
var allowedScopes = new List<string>() { "someScope" };
|
||||
|
||||
this.Given(_ => GivenTheFollowing(claimsPrincipal))
|
||||
.And(_ => GivenTheParserReturns(new OkResponse<List<string>>(allowedScopes)))
|
||||
.And(_ => GivenTheFollowing(allowedScopes))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new OkResponse<bool>(true)))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_match_scopes_and_return_error_result()
|
||||
{
|
||||
var fakeError = new FakeError();
|
||||
var claimsPrincipal = new ClaimsPrincipal();
|
||||
var allowedScopes = new List<string>() { "someScope" };
|
||||
var userScopes = new List<string>() { "anotherScope" };
|
||||
|
||||
this.Given(_ => GivenTheFollowing(claimsPrincipal))
|
||||
.And(_ => GivenTheParserReturns(new OkResponse<List<string>>(userScopes)))
|
||||
.And(_ => GivenTheFollowing(allowedScopes))
|
||||
.When(_ => WhenIAuthorise())
|
||||
.Then(_ => ThenTheFollowingIsReturned(new ErrorResponse<bool>(fakeError)))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheParserReturns(Response<List<string>> response)
|
||||
{
|
||||
_parser.Setup(x => x.GetValuesByClaimType(It.IsAny<IEnumerable<Claim>>(), It.IsAny<string>())).Returns(response);
|
||||
}
|
||||
|
||||
private void GivenTheFollowing(ClaimsPrincipal principal)
|
||||
{
|
||||
_principal = principal;
|
||||
}
|
||||
|
||||
private void GivenTheFollowing(List<string> allowedScopes)
|
||||
{
|
||||
_allowedScopes = allowedScopes;
|
||||
}
|
||||
|
||||
private void WhenIAuthorise()
|
||||
{
|
||||
_result = _authoriser.Authorise(_principal, _allowedScopes);
|
||||
}
|
||||
|
||||
private void ThenTheFollowingIsReturned(Response<bool> expected)
|
||||
{
|
||||
_result.Data.ShouldBe(expected.Data);
|
||||
_result.IsError.ShouldBe(expected.IsError);
|
||||
}
|
||||
}
|
||||
|
||||
public class FakeError : Error
|
||||
{
|
||||
public FakeError() : base("fake error", OcelotErrorCode.CannotAddDataError)
|
||||
public FakeError() : base("fake error", OcelotErrorCode.CannotAddDataError, 404)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,19 +21,19 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
private readonly CookieStickySessions _stickySessions;
|
||||
private readonly Mock<ILoadBalancer> _loadBalancer;
|
||||
private readonly int _defaultExpiryInMs;
|
||||
private DownstreamContext _downstreamContext;
|
||||
private Response<ServiceHostAndPort> _result;
|
||||
private Response<ServiceHostAndPort> _firstHostAndPort;
|
||||
private Response<ServiceHostAndPort> _secondHostAndPort;
|
||||
private readonly FakeBus<StickySession> _bus;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public CookieStickySessionsTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_bus = new FakeBus<StickySession>();
|
||||
_loadBalancer = new Mock<ILoadBalancer>();
|
||||
_defaultExpiryInMs = 0;
|
||||
_stickySessions = new CookieStickySessions(_loadBalancer.Object, "sessionid", _defaultExpiryInMs, _bus);
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -116,7 +116,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
private void GivenTheLoadBalancerReturnsError()
|
||||
{
|
||||
_loadBalancer
|
||||
.Setup(x => x.Lease(It.IsAny<DownstreamContext>()))
|
||||
.Setup(x => x.Lease(It.IsAny<HttpContext>()))
|
||||
.ReturnsAsync(new ErrorResponse<ServiceHostAndPort>(new AnyError()));
|
||||
}
|
||||
|
||||
@ -138,14 +138,14 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
var cookiesTwo = new FakeCookies();
|
||||
cookiesTwo.AddCookie("sessionid", "123");
|
||||
contextTwo.Request.Cookies = cookiesTwo;
|
||||
_firstHostAndPort = await _stickySessions.Lease(new DownstreamContext(contextOne));
|
||||
_secondHostAndPort = await _stickySessions.Lease(new DownstreamContext(contextTwo));
|
||||
_firstHostAndPort = await _stickySessions.Lease(contextOne);
|
||||
_secondHostAndPort = await _stickySessions.Lease(contextTwo);
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerReturnsSequence()
|
||||
{
|
||||
_loadBalancer
|
||||
.SetupSequence(x => x.Lease(It.IsAny<DownstreamContext>()))
|
||||
.SetupSequence(x => x.Lease(It.IsAny<HttpContext>()))
|
||||
.ReturnsAsync(new OkResponse<ServiceHostAndPort>(new ServiceHostAndPort("one", 80)))
|
||||
.ReturnsAsync(new OkResponse<ServiceHostAndPort>(new ServiceHostAndPort("two", 80)));
|
||||
}
|
||||
@ -158,8 +158,8 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
private async Task WhenILeaseTwiceInARow()
|
||||
{
|
||||
_firstHostAndPort = await _stickySessions.Lease(_downstreamContext);
|
||||
_secondHostAndPort = await _stickySessions.Lease(_downstreamContext);
|
||||
_firstHostAndPort = await _stickySessions.Lease(_httpContext);
|
||||
_secondHostAndPort = await _stickySessions.Lease(_httpContext);
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRequestHasSessionId(string value)
|
||||
@ -168,19 +168,19 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
var cookies = new FakeCookies();
|
||||
cookies.AddCookie("sessionid", value);
|
||||
context.Request.Cookies = cookies;
|
||||
_downstreamContext = new DownstreamContext(context);
|
||||
_httpContext = context;
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerReturns()
|
||||
{
|
||||
_loadBalancer
|
||||
.Setup(x => x.Lease(It.IsAny<DownstreamContext>()))
|
||||
.Setup(x => x.Lease(It.IsAny<HttpContext>()))
|
||||
.ReturnsAsync(new OkResponse<ServiceHostAndPort>(new ServiceHostAndPort("", 80)));
|
||||
}
|
||||
|
||||
private async Task WhenILease()
|
||||
{
|
||||
_result = await _stickySessions.Lease(_downstreamContext);
|
||||
_result = await _stickySessions.Lease(_httpContext);
|
||||
}
|
||||
|
||||
private void ThenTheHostAndPortIsNotNull()
|
||||
|
@ -14,6 +14,8 @@ using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
public class DelegateInvokingLoadBalancerCreatorTests
|
||||
{
|
||||
private DelegateInvokingLoadBalancerCreator<FakeLoadBalancer> _creator;
|
||||
@ -113,7 +115,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
public DownstreamReRoute ReRoute { get; }
|
||||
public IServiceDiscoveryProvider ServiceDiscoveryProvider { get; }
|
||||
|
||||
public Task<Response<ServiceHostAndPort>> Lease(DownstreamContext context)
|
||||
public Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -19,11 +19,11 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
private LeastConnection _leastConnection;
|
||||
private List<Service> _services;
|
||||
private Random _random;
|
||||
private DownstreamContext _context;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public LeastConnectionTests()
|
||||
{
|
||||
_context = new DownstreamContext(new DefaultHttpContext());
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_random = new Random();
|
||||
}
|
||||
|
||||
@ -64,9 +64,9 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(availableServices), serviceName);
|
||||
|
||||
var hostAndPortOne = _leastConnection.Lease(_context).Result;
|
||||
var hostAndPortOne = _leastConnection.Lease(_httpContext).Result;
|
||||
hostAndPortOne.Data.DownstreamHost.ShouldBe("127.0.0.1");
|
||||
var hostAndPortTwo = _leastConnection.Lease(_context).Result;
|
||||
var hostAndPortTwo = _leastConnection.Lease(_httpContext).Result;
|
||||
hostAndPortTwo.Data.DownstreamHost.ShouldBe("127.0.0.2");
|
||||
_leastConnection.Release(hostAndPortOne.Data);
|
||||
_leastConnection.Release(hostAndPortTwo.Data);
|
||||
@ -76,9 +76,9 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.1", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
hostAndPortOne = _leastConnection.Lease(_context).Result;
|
||||
hostAndPortOne = _leastConnection.Lease(_httpContext).Result;
|
||||
hostAndPortOne.Data.DownstreamHost.ShouldBe("127.0.0.1");
|
||||
hostAndPortTwo = _leastConnection.Lease(_context).Result;
|
||||
hostAndPortTwo = _leastConnection.Lease(_httpContext).Result;
|
||||
hostAndPortTwo.Data.DownstreamHost.ShouldBe("127.0.0.1");
|
||||
_leastConnection.Release(hostAndPortOne.Data);
|
||||
_leastConnection.Release(hostAndPortTwo.Data);
|
||||
@ -89,9 +89,9 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
new Service(serviceName, new ServiceHostAndPort("127.0.0.2", 80), string.Empty, string.Empty, new string[0]),
|
||||
};
|
||||
|
||||
hostAndPortOne = _leastConnection.Lease(_context).Result;
|
||||
hostAndPortOne = _leastConnection.Lease(_httpContext).Result;
|
||||
hostAndPortOne.Data.DownstreamHost.ShouldBe("127.0.0.1");
|
||||
hostAndPortTwo = _leastConnection.Lease(_context).Result;
|
||||
hostAndPortTwo = _leastConnection.Lease( _httpContext).Result;
|
||||
hostAndPortTwo.Data.DownstreamHost.ShouldBe("127.0.0.2");
|
||||
_leastConnection.Release(hostAndPortOne.Data);
|
||||
_leastConnection.Release(hostAndPortTwo.Data);
|
||||
@ -99,7 +99,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
private async Task LeaseDelayAndRelease()
|
||||
{
|
||||
var hostAndPort = await _leastConnection.Lease(_context);
|
||||
var hostAndPort = await _leastConnection.Lease(_httpContext);
|
||||
await Task.Delay(_random.Next(1, 100));
|
||||
_leastConnection.Release(hostAndPort.Data);
|
||||
}
|
||||
@ -138,15 +138,15 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
_services = availableServices;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
|
||||
var response = _leastConnection.Lease(_context).Result;
|
||||
var response = _leastConnection.Lease(_httpContext).Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease(_context).Result;
|
||||
response = _leastConnection.Lease(_httpContext).Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease(_context).Result;
|
||||
response = _leastConnection.Lease(_httpContext).Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[2].HostAndPort.DownstreamHost);
|
||||
}
|
||||
@ -165,19 +165,19 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
_services = availableServices;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
|
||||
var response = _leastConnection.Lease(_context).Result;
|
||||
var response = _leastConnection.Lease(_httpContext).Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease(_context).Result;
|
||||
response = _leastConnection.Lease(_httpContext).Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease(_context).Result;
|
||||
response = _leastConnection.Lease(_httpContext).Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease(_context).Result;
|
||||
response = _leastConnection.Lease(_httpContext).Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
}
|
||||
@ -196,26 +196,26 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
_services = availableServices;
|
||||
_leastConnection = new LeastConnection(() => Task.FromResult(_services), serviceName);
|
||||
|
||||
var response = _leastConnection.Lease(_context).Result;
|
||||
var response = _leastConnection.Lease(_httpContext).Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease(_context).Result;
|
||||
response = _leastConnection.Lease(_httpContext).Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease(_context).Result;
|
||||
response = _leastConnection.Lease(_httpContext).Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[0].HostAndPort.DownstreamHost);
|
||||
|
||||
response = _leastConnection.Lease(_context).Result;
|
||||
response = _leastConnection.Lease(_httpContext).Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
|
||||
//release this so 2 should have 1 connection and we should get 2 back as our next host and port
|
||||
_leastConnection.Release(availableServices[1].HostAndPort);
|
||||
|
||||
response = _leastConnection.Lease(_context).Result;
|
||||
response = _leastConnection.Lease(_httpContext).Result;
|
||||
|
||||
response.Data.DownstreamHost.ShouldBe(availableServices[1].HostAndPort.DownstreamHost);
|
||||
}
|
||||
@ -276,7 +276,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
private void WhenIGetTheNextHostAndPort()
|
||||
{
|
||||
_result = _leastConnection.Lease(_context).Result;
|
||||
_result = _leastConnection.Lease(_httpContext).Result;
|
||||
}
|
||||
|
||||
private void ThenTheNextHostAndPortIsReturned()
|
||||
|
@ -17,6 +17,7 @@ using Xunit;
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
public class LoadBalancerFactoryTests
|
||||
{
|
||||
@ -228,7 +229,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
private class FakeLoadBalancerOne : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease(DownstreamContext context)
|
||||
public Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
@ -241,7 +242,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
private class FakeLoadBalancerTwo : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease(DownstreamContext context)
|
||||
public Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
@ -254,7 +255,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
private class FakeNoLoadBalancer : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease(DownstreamContext context)
|
||||
public Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
@ -267,7 +268,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
private class BrokenLoadBalancer : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease(DownstreamContext context)
|
||||
public Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
public class LoadBalancerHouseTests
|
||||
{
|
||||
private DownstreamReRoute _reRoute;
|
||||
@ -155,7 +157,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
private class FakeLoadBalancer : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease(DownstreamContext context)
|
||||
public Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
@ -168,7 +170,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
private class FakeRoundRobinLoadBalancer : ILoadBalancer
|
||||
{
|
||||
public Task<Response<ServiceHostAndPort>> Lease(DownstreamContext context)
|
||||
public Task<Response<ServiceHostAndPort>> Lease(HttpContext httpContext)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -1,7 +1,3 @@
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@ -19,8 +15,13 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class LoadBalancerMiddlewareTests
|
||||
{
|
||||
@ -34,21 +35,22 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private LoadBalancingMiddleware _middleware;
|
||||
private DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
private RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
private Mock<IRequestScopedDataRepository> _repo;
|
||||
|
||||
public LoadBalancerMiddlewareTests()
|
||||
{
|
||||
_repo = new Mock<IRequestScopedDataRepository>();
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
||||
_loadBalancer = new Mock<ILoadBalancer>();
|
||||
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
|
||||
_downstreamRequest = new HttpRequestMessage(HttpMethod.Get, "http://test.com/");
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<LoadBalancingMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(_downstreamRequest);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -133,34 +135,34 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware = new LoadBalancingMiddleware(_next, _loggerFactory.Object, _loadBalancerHouse.Object);
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheConfigurationIs(ServiceProviderConfiguration config)
|
||||
{
|
||||
_config = config;
|
||||
var configuration = new InternalConfiguration(null, null, config, null, null, null, null, null, null);
|
||||
_downstreamContext.Configuration = configuration;
|
||||
_httpContext.Items.SetIInternalConfiguration(configuration);
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamUrlIs(string downstreamUrl)
|
||||
{
|
||||
_downstreamRequest.RequestUri = new System.Uri(downstreamUrl);
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(_downstreamRequest);
|
||||
_downstreamRequest.RequestUri = new Uri(downstreamUrl);
|
||||
_httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(_downstreamRequest));
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerReturnsAnError()
|
||||
{
|
||||
_getHostAndPortError = new ErrorResponse<ServiceHostAndPort>(new List<Error>() { new ServicesAreNullError($"services were null for bah") });
|
||||
_loadBalancer
|
||||
.Setup(x => x.Lease(It.IsAny<DownstreamContext>()))
|
||||
.Setup(x => x.Lease(It.IsAny<HttpContext>()))
|
||||
.ReturnsAsync(_getHostAndPortError);
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerReturnsOk()
|
||||
{
|
||||
_loadBalancer
|
||||
.Setup(x => x.Lease(It.IsAny<DownstreamContext>()))
|
||||
.Setup(x => x.Lease(It.IsAny<HttpContext>()))
|
||||
.ReturnsAsync(new OkResponse<ServiceHostAndPort>(new ServiceHostAndPort("abc", 123, "https")));
|
||||
}
|
||||
|
||||
@ -168,14 +170,14 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
{
|
||||
_hostAndPort = new ServiceHostAndPort("127.0.0.1", 80);
|
||||
_loadBalancer
|
||||
.Setup(x => x.Lease(It.IsAny<DownstreamContext>()))
|
||||
.Setup(x => x.Lease(It.IsAny<HttpContext>()))
|
||||
.ReturnsAsync(new OkResponse<ServiceHostAndPort>(_hostAndPort));
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamReRoute downstreamRoute, List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue> placeholder)
|
||||
{
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues = placeholder;
|
||||
_downstreamContext.DownstreamReRoute = downstreamRoute;
|
||||
_httpContext.Items.UpsertTemplatePlaceholderNameAndValues(placeholder);
|
||||
_httpContext.Items.UpsertDownstreamReRoute(downstreamRoute);
|
||||
}
|
||||
|
||||
private void GivenTheLoadBalancerHouseReturns()
|
||||
@ -199,32 +201,32 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
private void ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline()
|
||||
{
|
||||
_downstreamContext.IsError.ShouldBeTrue();
|
||||
_downstreamContext.Errors.ShouldBe(_getLoadBalancerHouseError.Errors);
|
||||
_httpContext.Items.Errors().Count.ShouldBeGreaterThan(0);
|
||||
_httpContext.Items.Errors().ShouldBe(_getLoadBalancerHouseError.Errors);
|
||||
}
|
||||
|
||||
private void ThenAnErrorSayingReleaseFailedIsSetOnThePipeline()
|
||||
{
|
||||
_downstreamContext.IsError.ShouldBeTrue();
|
||||
_downstreamContext.Errors.ShouldBe(It.IsAny<List<Error>>());
|
||||
_httpContext.Items.Errors().Count.ShouldBeGreaterThan(0);
|
||||
_httpContext.Items.Errors().ShouldBe(It.IsAny<List<Error>>());
|
||||
}
|
||||
|
||||
private void ThenAnErrorStatingHostAndPortCouldNotBeFoundIsSetOnPipeline()
|
||||
{
|
||||
_downstreamContext.IsError.ShouldBeTrue();
|
||||
_downstreamContext.Errors.ShouldBe(_getHostAndPortError.Errors);
|
||||
_httpContext.Items.Errors().Count.ShouldBeGreaterThan(0);
|
||||
_httpContext.Items.Errors().ShouldBe(_getHostAndPortError.Errors);
|
||||
}
|
||||
|
||||
private void ThenAnHostAndPortIsSetOnPipeline()
|
||||
{
|
||||
_downstreamContext.DownstreamRequest.Host.ShouldBeEquivalentTo("abc");
|
||||
_downstreamContext.DownstreamRequest.Port.ShouldBeEquivalentTo(123);
|
||||
_downstreamContext.DownstreamRequest.Scheme.ShouldBeEquivalentTo("https");
|
||||
_httpContext.Items.DownstreamRequest().Host.ShouldBeEquivalentTo("abc");
|
||||
_httpContext.Items.DownstreamRequest().Port.ShouldBeEquivalentTo(123);
|
||||
_httpContext.Items.DownstreamRequest().Scheme.ShouldBeEquivalentTo("https");
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamUrlIsReplacedWith(string expectedUri)
|
||||
{
|
||||
_downstreamContext.DownstreamRequest.ToHttpRequestMessage().RequestUri.OriginalString.ShouldBe(expectedUri);
|
||||
_httpContext.Items.DownstreamRequest().ToHttpRequestMessage().RequestUri.OriginalString.ShouldBe(expectedUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
private void WhenIGetTheNextHostAndPort()
|
||||
{
|
||||
_result = _loadBalancer.Lease(new DownstreamContext(new DefaultHttpContext())).Result;
|
||||
_result = _loadBalancer.Lease(new DefaultHttpContext()).Result;
|
||||
}
|
||||
|
||||
private void ThenTheHostAndPortIs(ServiceHostAndPort expected)
|
||||
|
@ -17,12 +17,11 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
private readonly RoundRobin _roundRobin;
|
||||
private readonly List<Service> _services;
|
||||
private Response<ServiceHostAndPort> _hostAndPort;
|
||||
private DownstreamContext _context;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public RoundRobinTests()
|
||||
{
|
||||
_context = new DownstreamContext(new DefaultHttpContext());
|
||||
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_services = new List<Service>
|
||||
{
|
||||
new Service("product", new ServiceHostAndPort("127.0.0.1", 5000), string.Empty, string.Empty, new string[0]),
|
||||
@ -52,18 +51,18 @@ namespace Ocelot.UnitTests.LoadBalancer
|
||||
|
||||
while (stopWatch.ElapsedMilliseconds < 1000)
|
||||
{
|
||||
var address = _roundRobin.Lease(_context).Result;
|
||||
var address = _roundRobin.Lease(_httpContext).Result;
|
||||
address.Data.ShouldBe(_services[0].HostAndPort);
|
||||
address = _roundRobin.Lease(_context).Result;
|
||||
address = _roundRobin.Lease(_httpContext).Result;
|
||||
address.Data.ShouldBe(_services[1].HostAndPort);
|
||||
address = _roundRobin.Lease(_context).Result;
|
||||
address = _roundRobin.Lease(_httpContext).Result;
|
||||
address.Data.ShouldBe(_services[2].HostAndPort);
|
||||
}
|
||||
}
|
||||
|
||||
private void GivenIGetTheNextAddress()
|
||||
{
|
||||
_hostAndPort = _roundRobin.Lease(_context).Result;
|
||||
_hostAndPort = _roundRobin.Lease(_httpContext).Result;
|
||||
}
|
||||
|
||||
private void ThenTheNextAddressIndexIs(int index)
|
||||
|
@ -2,7 +2,6 @@ using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using System;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
@ -16,12 +15,13 @@ namespace Ocelot.UnitTests.Logging
|
||||
private readonly Mock<IOcelotLogger> _logger;
|
||||
private IServiceCollection _serviceCollection;
|
||||
private IServiceProvider _serviceProvider;
|
||||
private DownstreamContext _downstreamContext;
|
||||
private string _name;
|
||||
private Exception _exception;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public OcelotDiagnosticListenerTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_factory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_serviceCollection = new ServiceCollection();
|
||||
@ -30,44 +30,12 @@ namespace Ocelot.UnitTests.Logging
|
||||
_listener = new OcelotDiagnosticListener(_factory.Object, _serviceProvider);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_trace_ocelot_middleware_started()
|
||||
{
|
||||
this.Given(_ => GivenAMiddlewareName())
|
||||
.And(_ => GivenAContext())
|
||||
.When(_ => WhenOcelotMiddlewareStartedCalled())
|
||||
.Then(_ => ThenTheLogIs($"Ocelot.MiddlewareStarted: {_name}; {_downstreamContext.HttpContext.Request.Path}"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_trace_ocelot_middleware_finished()
|
||||
{
|
||||
this.Given(_ => GivenAMiddlewareName())
|
||||
.And(_ => GivenAContext())
|
||||
.When(_ => WhenOcelotMiddlewareFinishedCalled())
|
||||
.Then(_ => ThenTheLogIs($"Ocelot.MiddlewareFinished: {_name}; {_downstreamContext.HttpContext.Request.Path}"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_trace_ocelot_middleware_exception()
|
||||
{
|
||||
this.Given(_ => GivenAMiddlewareName())
|
||||
.And(_ => GivenAContext())
|
||||
.And(_ => GivenAException(new Exception("oh no")))
|
||||
.When(_ => WhenOcelotMiddlewareExceptionCalled())
|
||||
.Then(_ => ThenTheLogIs($"Ocelot.MiddlewareException: {_name}; {_exception.Message};"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_trace_middleware_started()
|
||||
{
|
||||
this.Given(_ => GivenAMiddlewareName())
|
||||
.And(_ => GivenAContext())
|
||||
.When(_ => WhenMiddlewareStartedCalled())
|
||||
.Then(_ => ThenTheLogIs($"MiddlewareStarting: {_name}; {_downstreamContext.HttpContext.Request.Path}"))
|
||||
.Then(_ => ThenTheLogIs($"MiddlewareStarting: {_name}; {_httpContext.Request.Path}"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
@ -75,9 +43,8 @@ namespace Ocelot.UnitTests.Logging
|
||||
public void should_trace_middleware_finished()
|
||||
{
|
||||
this.Given(_ => GivenAMiddlewareName())
|
||||
.And(_ => GivenAContext())
|
||||
.When(_ => WhenMiddlewareFinishedCalled())
|
||||
.Then(_ => ThenTheLogIs($"MiddlewareFinished: {_name}; {_downstreamContext.HttpContext.Response.StatusCode}"))
|
||||
.Then(_ => ThenTheLogIs($"MiddlewareFinished: {_name}; {_httpContext.Response.StatusCode}"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
@ -85,7 +52,6 @@ namespace Ocelot.UnitTests.Logging
|
||||
public void should_trace_middleware_exception()
|
||||
{
|
||||
this.Given(_ => GivenAMiddlewareName())
|
||||
.And(_ => GivenAContext())
|
||||
.And(_ => GivenAException(new Exception("oh no")))
|
||||
.When(_ => WhenMiddlewareExceptionCalled())
|
||||
.Then(_ => ThenTheLogIs($"MiddlewareException: {_name}; {_exception.Message};"))
|
||||
@ -97,29 +63,14 @@ namespace Ocelot.UnitTests.Logging
|
||||
_exception = exception;
|
||||
}
|
||||
|
||||
private void WhenOcelotMiddlewareStartedCalled()
|
||||
{
|
||||
_listener.OcelotMiddlewareStarted(_downstreamContext, _name);
|
||||
}
|
||||
|
||||
private void WhenOcelotMiddlewareFinishedCalled()
|
||||
{
|
||||
_listener.OcelotMiddlewareFinished(_downstreamContext, _name);
|
||||
}
|
||||
|
||||
private void WhenOcelotMiddlewareExceptionCalled()
|
||||
{
|
||||
_listener.OcelotMiddlewareException(_exception, _downstreamContext, _name);
|
||||
}
|
||||
|
||||
private void WhenMiddlewareStartedCalled()
|
||||
{
|
||||
_listener.OnMiddlewareStarting(_downstreamContext.HttpContext, _name);
|
||||
_listener.OnMiddlewareStarting(_httpContext, _name);
|
||||
}
|
||||
|
||||
private void WhenMiddlewareFinishedCalled()
|
||||
{
|
||||
_listener.OnMiddlewareFinished(_downstreamContext.HttpContext, _name);
|
||||
_listener.OnMiddlewareFinished(_httpContext, _name);
|
||||
}
|
||||
|
||||
private void WhenMiddlewareExceptionCalled()
|
||||
@ -127,11 +78,6 @@ namespace Ocelot.UnitTests.Logging
|
||||
_listener.OnMiddlewareException(_exception, _name);
|
||||
}
|
||||
|
||||
private void GivenAContext()
|
||||
{
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
}
|
||||
|
||||
private void GivenAMiddlewareName()
|
||||
{
|
||||
_name = "name";
|
||||
|
@ -1,71 +0,0 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
using Shouldly;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Middleware
|
||||
{
|
||||
public class MultiplexerTests
|
||||
{
|
||||
private readonly Multiplexer _multiplexer;
|
||||
private readonly DownstreamContext _context;
|
||||
private ReRoute _reRoute;
|
||||
private readonly OcelotRequestDelegate _pipeline;
|
||||
private int _count;
|
||||
private Mock<IResponseAggregator> _aggregator;
|
||||
private Mock<IResponseAggregatorFactory> _factory;
|
||||
|
||||
public MultiplexerTests()
|
||||
{
|
||||
_factory = new Mock<IResponseAggregatorFactory>();
|
||||
_aggregator = new Mock<IResponseAggregator>();
|
||||
_context = new DownstreamContext(new DefaultHttpContext());
|
||||
_pipeline = context => Task.FromResult(_count++);
|
||||
_factory.Setup(x => x.Get(It.IsAny<ReRoute>())).Returns(_aggregator.Object);
|
||||
_multiplexer = new Multiplexer(_factory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_multiplex()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().WithDownstreamReRoute(new DownstreamReRouteBuilder().Build()).WithDownstreamReRoute(new DownstreamReRouteBuilder().Build()).Build();
|
||||
|
||||
this.Given(x => GivenTheFollowing(reRoute))
|
||||
.When(x => WhenIMultiplex())
|
||||
.Then(x => ThePipelineIsCalled(2))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_multiplex()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().WithDownstreamReRoute(new DownstreamReRouteBuilder().Build()).Build();
|
||||
|
||||
this.Given(x => GivenTheFollowing(reRoute))
|
||||
.When(x => WhenIMultiplex())
|
||||
.Then(x => ThePipelineIsCalled(1))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheFollowing(ReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void WhenIMultiplex()
|
||||
{
|
||||
_multiplexer.Multiplex(_context, _reRoute, _pipeline).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThePipelineIsCalled(int expected)
|
||||
{
|
||||
_count.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.UnitTests.Responder;
|
||||
using System.Collections.Generic;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Middleware
|
||||
{
|
||||
public class OcelotMiddlewareTests
|
||||
{
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private FakeMiddleware _middleware;
|
||||
private List<Error> _errors;
|
||||
|
||||
public OcelotMiddlewareTests()
|
||||
{
|
||||
_errors = new List<Error>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_middleware = new FakeMiddleware(_logger.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_log_error()
|
||||
{
|
||||
this.Given(x => GivenAnError(new AnyError()))
|
||||
.When(x => WhenISetTheError())
|
||||
.Then(x => ThenTheErrorIsLogged(1))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_log_errors()
|
||||
{
|
||||
this.Given(x => GivenAnError(new AnyError()))
|
||||
.And(x => GivenAnError(new AnyError()))
|
||||
.When(x => WhenISetTheErrors())
|
||||
.Then(x => ThenTheErrorIsLogged(2))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenISetTheErrors()
|
||||
{
|
||||
_middleware.SetPipelineError(new DownstreamContext(new DefaultHttpContext()), _errors);
|
||||
}
|
||||
|
||||
private void ThenTheErrorIsLogged(int times)
|
||||
{
|
||||
_logger.Verify(x => x.LogWarning("blahh"), Times.Exactly(times));
|
||||
}
|
||||
|
||||
private void WhenISetTheError()
|
||||
{
|
||||
_middleware.SetPipelineError(new DownstreamContext(new DefaultHttpContext()), _errors[0]);
|
||||
}
|
||||
|
||||
private void GivenAnError(Error error)
|
||||
{
|
||||
_errors.Add(error);
|
||||
}
|
||||
}
|
||||
|
||||
public class FakeMiddleware : OcelotMiddleware
|
||||
{
|
||||
public FakeMiddleware(IOcelotLogger logger)
|
||||
: base(logger)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
namespace Ocelot.UnitTests.Middleware
|
||||
{
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.DependencyInjection;
|
||||
@ -7,7 +9,6 @@ namespace Ocelot.UnitTests.Middleware
|
||||
using Ocelot.DownstreamUrlCreator.Middleware;
|
||||
using Ocelot.LoadBalancer.Middleware;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Middleware.Pipeline;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.WebSockets.Middleware;
|
||||
using Shouldly;
|
||||
@ -16,8 +17,8 @@ namespace Ocelot.UnitTests.Middleware
|
||||
|
||||
public class OcelotPipelineExtensionsTests
|
||||
{
|
||||
private OcelotPipelineBuilder _builder;
|
||||
private OcelotRequestDelegate _handlers;
|
||||
private ApplicationBuilder _builder;
|
||||
private RequestDelegate _handlers;
|
||||
|
||||
[Fact]
|
||||
public void should_set_up_pipeline()
|
||||
@ -50,15 +51,14 @@ namespace Ocelot.UnitTests.Middleware
|
||||
private void WhenIExpandBuild()
|
||||
{
|
||||
OcelotPipelineConfiguration configuration = new OcelotPipelineConfiguration();
|
||||
configuration.MapWhenOcelotPipeline.Add((app) =>
|
||||
//Func<HttpContext, bool>, Action<IApplicationBuilder>
|
||||
configuration.MapWhenOcelotPipeline.Add((httpContext) => httpContext.WebSockets.IsWebSocketRequest, app =>
|
||||
{
|
||||
app.UseDownstreamRouteFinderMiddleware();
|
||||
app.UseDownstreamRequestInitialiser();
|
||||
app.UseLoadBalancingMiddleware();
|
||||
app.UseDownstreamUrlCreatorMiddleware();
|
||||
app.UseWebSocketsProxyMiddleware();
|
||||
|
||||
return context => context.HttpContext.WebSockets.IsWebSocketRequest;
|
||||
});
|
||||
_handlers = _builder.BuildOcelotPipeline(new OcelotPipelineConfiguration());
|
||||
}
|
||||
@ -71,7 +71,7 @@ namespace Ocelot.UnitTests.Middleware
|
||||
services.AddSingleton<IConfiguration>(root);
|
||||
services.AddOcelot();
|
||||
var provider = services.BuildServiceProvider();
|
||||
_builder = new OcelotPipelineBuilder(provider);
|
||||
_builder = new ApplicationBuilder(provider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ocelot.UnitTests.Middleware
|
||||
namespace Ocelot.UnitTests.Middleware
|
||||
{
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
@ -11,19 +8,22 @@ namespace Ocelot.UnitTests.Middleware
|
||||
using Ocelot.DependencyInjection;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Middleware.Pipeline;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Ocelot.Errors.Middleware;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
public class OcelotPiplineBuilderTests
|
||||
{
|
||||
private readonly IServiceCollection _services;
|
||||
private readonly IConfiguration _configRoot;
|
||||
private DownstreamContext _downstreamContext;
|
||||
private int _counter;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public OcelotPiplineBuilderTests()
|
||||
{
|
||||
@ -32,6 +32,7 @@ namespace Ocelot.UnitTests.Middleware
|
||||
_services.AddSingleton<IWebHostEnvironment>(GetHostingEnvironment());
|
||||
_services.AddSingleton<IConfiguration>(_configRoot);
|
||||
_services.AddOcelot();
|
||||
_httpContext = new DefaultHttpContext();
|
||||
}
|
||||
|
||||
|
||||
@ -64,61 +65,58 @@ namespace Ocelot.UnitTests.Middleware
|
||||
private void WhenIUseAGeneric()
|
||||
{
|
||||
var provider = _services.BuildServiceProvider();
|
||||
IOcelotPipelineBuilder builder = new OcelotPipelineBuilder(provider);
|
||||
builder = builder.UseMiddleware<Ocelot.Errors.Middleware.ExceptionHandlerMiddleware>();
|
||||
IApplicationBuilder builder = new ApplicationBuilder(provider);
|
||||
builder = builder.UseMiddleware<ExceptionHandlerMiddleware>();
|
||||
var del = builder.Build();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
del.Invoke(_downstreamContext);
|
||||
del.Invoke(_httpContext);
|
||||
}
|
||||
|
||||
private void ThenTheGenericIsInThePipeline()
|
||||
{
|
||||
_downstreamContext.HttpContext.Response.StatusCode.ShouldBe(500);
|
||||
_httpContext.Response.StatusCode.ShouldBe(500);
|
||||
}
|
||||
|
||||
private void WhenIUseAFunc()
|
||||
{
|
||||
_counter = 0;
|
||||
var provider = _services.BuildServiceProvider();
|
||||
IOcelotPipelineBuilder builder = new OcelotPipelineBuilder(provider);
|
||||
IApplicationBuilder builder = new ApplicationBuilder(provider);
|
||||
builder = builder.Use(async (ctx, next) =>
|
||||
{
|
||||
_counter++;
|
||||
await next.Invoke();
|
||||
});
|
||||
var del = builder.Build();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
del.Invoke(_downstreamContext);
|
||||
del.Invoke(_httpContext);
|
||||
}
|
||||
|
||||
private void ThenTheFuncIsInThePipeline()
|
||||
{
|
||||
_counter.ShouldBe(1);
|
||||
_downstreamContext.HttpContext.Response.StatusCode.ShouldBe(404);
|
||||
_httpContext.Response.StatusCode.ShouldBe(404);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Middleware_Multi_Parameters_Invoke()
|
||||
{
|
||||
var provider = _services.BuildServiceProvider();
|
||||
IOcelotPipelineBuilder builder = new OcelotPipelineBuilder(provider);
|
||||
IApplicationBuilder builder = new ApplicationBuilder(provider);
|
||||
builder = builder.UseMiddleware<MultiParametersInvokeMiddleware>();
|
||||
var del = builder.Build();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
del.Invoke(_downstreamContext);
|
||||
del.Invoke(_httpContext);
|
||||
}
|
||||
|
||||
private class MultiParametersInvokeMiddleware : OcelotMiddleware
|
||||
{
|
||||
private readonly OcelotRequestDelegate _next;
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
public MultiParametersInvokeMiddleware(OcelotRequestDelegate next)
|
||||
public MultiParametersInvokeMiddleware(RequestDelegate next)
|
||||
: base(new FakeLogger())
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public Task Invoke(DownstreamContext context, IServiceProvider serviceProvider)
|
||||
public Task Invoke(HttpContext context, IServiceProvider serviceProvider)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
@ -1,86 +1,86 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using static Ocelot.UnitTests.Middleware.UserDefinedResponseAggregatorTests;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Multiplexer;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using static Ocelot.UnitTests.Multiplexing.UserDefinedResponseAggregatorTests;
|
||||
|
||||
namespace Ocelot.UnitTests.Middleware
|
||||
{
|
||||
public class DefinedAggregatorProviderTests
|
||||
{
|
||||
private ServiceLocatorDefinedAggregatorProvider _provider;
|
||||
private Response<IDefinedAggregator> _aggregator;
|
||||
private ReRoute _reRoute;
|
||||
|
||||
[Fact]
|
||||
public void should_find_aggregator()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithAggregator("TestDefinedAggregator")
|
||||
.Build();
|
||||
|
||||
this.Given(_ => GivenDefinedAggregator())
|
||||
.And(_ => GivenReRoute(reRoute))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheAggregatorIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_find_aggregator()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithAggregator("TestDefinedAggregator")
|
||||
.Build();
|
||||
|
||||
this.Given(_ => GivenNoDefinedAggregator())
|
||||
.And(_ => GivenReRoute(reRoute))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenAnErrorIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenDefinedAggregator()
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton<IDefinedAggregator, TestDefinedAggregator>();
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
_provider = new ServiceLocatorDefinedAggregatorProvider(services);
|
||||
}
|
||||
|
||||
private void ThenTheAggregatorIsReturned()
|
||||
{
|
||||
_aggregator.Data.ShouldNotBeNull();
|
||||
_aggregator.Data.ShouldBeOfType<TestDefinedAggregator>();
|
||||
_aggregator.IsError.ShouldBeFalse();
|
||||
}
|
||||
|
||||
private void GivenNoDefinedAggregator()
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
_provider = new ServiceLocatorDefinedAggregatorProvider(services);
|
||||
}
|
||||
|
||||
private void GivenReRoute(ReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void WhenIGet()
|
||||
{
|
||||
_aggregator = _provider.Get(_reRoute);
|
||||
}
|
||||
|
||||
private void ThenAnErrorIsReturned()
|
||||
{
|
||||
_aggregator.IsError.ShouldBeTrue();
|
||||
_aggregator.Errors[0].Message.ShouldBe("Could not find Aggregator: TestDefinedAggregator");
|
||||
_aggregator.Errors[0].ShouldBeOfType<CouldNotFindAggregatorError>();
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.UnitTests.Multiplexing
|
||||
{
|
||||
public class DefinedAggregatorProviderTests
|
||||
{
|
||||
private ServiceLocatorDefinedAggregatorProvider _provider;
|
||||
private Response<IDefinedAggregator> _aggregator;
|
||||
private ReRoute _reRoute;
|
||||
|
||||
[Fact]
|
||||
public void should_find_aggregator()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithAggregator("TestDefinedAggregator")
|
||||
.Build();
|
||||
|
||||
this.Given(_ => GivenDefinedAggregator())
|
||||
.And(_ => GivenReRoute(reRoute))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheAggregatorIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_find_aggregator()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithAggregator("TestDefinedAggregator")
|
||||
.Build();
|
||||
|
||||
this.Given(_ => GivenNoDefinedAggregator())
|
||||
.And(_ => GivenReRoute(reRoute))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenAnErrorIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenDefinedAggregator()
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.AddSingleton<IDefinedAggregator, TestDefinedAggregator>();
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
_provider = new ServiceLocatorDefinedAggregatorProvider(services);
|
||||
}
|
||||
|
||||
private void ThenTheAggregatorIsReturned()
|
||||
{
|
||||
_aggregator.Data.ShouldNotBeNull();
|
||||
_aggregator.Data.ShouldBeOfType<TestDefinedAggregator>();
|
||||
_aggregator.IsError.ShouldBeFalse();
|
||||
}
|
||||
|
||||
private void GivenNoDefinedAggregator()
|
||||
{
|
||||
var serviceCollection = new ServiceCollection();
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
_provider = new ServiceLocatorDefinedAggregatorProvider(services);
|
||||
}
|
||||
|
||||
private void GivenReRoute(ReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void WhenIGet()
|
||||
{
|
||||
_aggregator = _provider.Get(_reRoute);
|
||||
}
|
||||
|
||||
private void ThenAnErrorIsReturned()
|
||||
{
|
||||
_aggregator.IsError.ShouldBeTrue();
|
||||
_aggregator.Errors[0].Message.ShouldBe("Could not find Aggregator: TestDefinedAggregator");
|
||||
_aggregator.Errors[0].ShouldBeOfType<CouldNotFindAggregatorError>();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
namespace Ocelot.UnitTests.Multiplexing
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Multiplexer;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class MultiplexingMiddlewareTests
|
||||
{
|
||||
private readonly MultiplexingMiddleware _middleware;
|
||||
private DownstreamRoute _downstreamRoute;
|
||||
private int _count;
|
||||
private Mock<IResponseAggregator> _aggregator;
|
||||
private Mock<IResponseAggregatorFactory> _factory;
|
||||
private HttpContext _httpContext;
|
||||
private RequestDelegate _next;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
|
||||
public MultiplexingMiddlewareTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_factory = new Mock<IResponseAggregatorFactory>();
|
||||
_aggregator = new Mock<IResponseAggregator>();
|
||||
_factory.Setup(x => x.Get(It.IsAny<ReRoute>())).Returns(_aggregator.Object);
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<MultiplexingMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.FromResult(_count++);
|
||||
_middleware = new MultiplexingMiddleware(_next, _loggerFactory.Object, _factory.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_multiplex()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().WithDownstreamReRoute(new DownstreamReRouteBuilder().Build()).WithDownstreamReRoute(new DownstreamReRouteBuilder().Build()).Build();
|
||||
|
||||
this.Given(x => GivenTheFollowing(reRoute))
|
||||
.When(x => WhenIMultiplex())
|
||||
.Then(x => ThePipelineIsCalled(2))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_multiplex()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().WithDownstreamReRoute(new DownstreamReRouteBuilder().Build()).Build();
|
||||
|
||||
this.Given(x => GivenTheFollowing(reRoute))
|
||||
.When(x => WhenIMultiplex())
|
||||
.Then(x => ThePipelineIsCalled(1))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheFollowing(ReRoute reRoute)
|
||||
{
|
||||
_downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute);
|
||||
_httpContext.Items.UpsertDownstreamRoute(_downstreamRoute);
|
||||
}
|
||||
|
||||
private void WhenIMultiplex()
|
||||
{
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThePipelineIsCalled(int expected)
|
||||
{
|
||||
_count.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,65 +1,65 @@
|
||||
namespace Ocelot.UnitTests.Middleware
|
||||
{
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class ResponseAggregatorFactoryTests
|
||||
{
|
||||
private readonly InMemoryResponseAggregatorFactory _factory;
|
||||
private Mock<IDefinedAggregatorProvider> _provider;
|
||||
private ReRoute _reRoute;
|
||||
private IResponseAggregator _aggregator;
|
||||
|
||||
public ResponseAggregatorFactoryTests()
|
||||
{
|
||||
_provider = new Mock<IDefinedAggregatorProvider>();
|
||||
_aggregator = new SimpleJsonResponseAggregator();
|
||||
_factory = new InMemoryResponseAggregatorFactory(_provider.Object, _aggregator);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_simple_json_aggregator()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(_ => GivenReRoute(reRoute))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheAggregatorIs<SimpleJsonResponseAggregator>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_user_defined_aggregator()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithAggregator("doesntmatter")
|
||||
.Build();
|
||||
|
||||
this.Given(_ => GivenReRoute(reRoute))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheAggregatorIs<UserDefinedResponseAggregator>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenReRoute(ReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void WhenIGet()
|
||||
{
|
||||
_aggregator = _factory.Get(_reRoute);
|
||||
}
|
||||
|
||||
private void ThenTheAggregatorIs<T>()
|
||||
{
|
||||
_aggregator.ShouldBeOfType<T>();
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace Ocelot.UnitTests.Multiplexing
|
||||
{
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Multiplexer;
|
||||
using Shouldly;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class ResponseAggregatorFactoryTests
|
||||
{
|
||||
private readonly InMemoryResponseAggregatorFactory _factory;
|
||||
private Mock<IDefinedAggregatorProvider> _provider;
|
||||
private ReRoute _reRoute;
|
||||
private IResponseAggregator _aggregator;
|
||||
|
||||
public ResponseAggregatorFactoryTests()
|
||||
{
|
||||
_provider = new Mock<IDefinedAggregatorProvider>();
|
||||
_aggregator = new SimpleJsonResponseAggregator();
|
||||
_factory = new InMemoryResponseAggregatorFactory(_provider.Object, _aggregator);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_simple_json_aggregator()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.Build();
|
||||
|
||||
this.Given(_ => GivenReRoute(reRoute))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheAggregatorIs<SimpleJsonResponseAggregator>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_user_defined_aggregator()
|
||||
{
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithAggregator("doesntmatter")
|
||||
.Build();
|
||||
|
||||
this.Given(_ => GivenReRoute(reRoute))
|
||||
.When(_ => WhenIGet())
|
||||
.Then(_ => ThenTheAggregatorIs<UserDefinedResponseAggregator>())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenReRoute(ReRoute reRoute)
|
||||
{
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void WhenIGet()
|
||||
{
|
||||
_aggregator = _factory.Get(_reRoute);
|
||||
}
|
||||
|
||||
private void ThenTheAggregatorIs<T>()
|
||||
{
|
||||
_aggregator.ShouldBeOfType<T>();
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Configuration.File;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
using Ocelot.Multiplexer;
|
||||
using Ocelot.UnitTests.Responder;
|
||||
using Ocelot.Values;
|
||||
using Shouldly;
|
||||
@ -15,13 +15,13 @@ using System.Text;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Middleware
|
||||
namespace Ocelot.UnitTests.Multiplexing
|
||||
{
|
||||
public class SimpleJsonResponseAggregatorTests
|
||||
{
|
||||
private readonly SimpleJsonResponseAggregator _aggregator;
|
||||
private List<DownstreamContext> _downstreamContexts;
|
||||
private DownstreamContext _upstreamContext;
|
||||
private List<HttpContext> _downstreamContexts;
|
||||
private HttpContext _upstreamContext;
|
||||
private ReRoute _reRoute;
|
||||
|
||||
public SimpleJsonResponseAggregatorTests()
|
||||
@ -53,24 +53,21 @@ namespace Ocelot.UnitTests.Middleware
|
||||
.Build();
|
||||
|
||||
var commentsResponseContent = @"[{""id"":1,""writerId"":1,""postId"":1,""text"":""text1""},{""id"":2,""writerId"":2,""postId"":2,""text"":""text2""},{""id"":3,""writerId"":2,""postId"":1,""text"":""text21""}]";
|
||||
var commentsDownstreamContext = new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamResponse = new DownstreamResponse(new StringContent(commentsResponseContent, Encoding.UTF8, "application/json"), HttpStatusCode.OK, new EditableList<KeyValuePair<string, IEnumerable<string>>>(), "some reason"),
|
||||
DownstreamReRoute = commentsDownstreamReRoute
|
||||
};
|
||||
|
||||
var commentsDownstreamContext = new DefaultHttpContext();
|
||||
commentsDownstreamContext.Items.UpsertDownstreamResponse(new DownstreamResponse(new StringContent(commentsResponseContent, Encoding.UTF8, "application/json"), HttpStatusCode.OK, new EditableList<KeyValuePair<string, IEnumerable<string>>>(), "some reason"));
|
||||
commentsDownstreamContext.Items.UpsertDownstreamReRoute(commentsDownstreamReRoute);
|
||||
|
||||
var userDetailsResponseContent = @"[{""id"":1,""firstName"":""abolfazl"",""lastName"":""rajabpour""},{""id"":2,""firstName"":""reza"",""lastName"":""rezaei""}]";
|
||||
var userDetailsDownstreamContext = new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamResponse = new DownstreamResponse(new StringContent(userDetailsResponseContent, Encoding.UTF8, "application/json"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"),
|
||||
DownstreamReRoute = userDetailsDownstreamReRoute
|
||||
};
|
||||
var userDetailsDownstreamContext = new DefaultHttpContext();
|
||||
userDetailsDownstreamContext.Items.UpsertDownstreamResponse(new DownstreamResponse(new StringContent(userDetailsResponseContent, Encoding.UTF8, "application/json"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"));
|
||||
userDetailsDownstreamContext.Items.UpsertDownstreamReRoute(userDetailsDownstreamReRoute);
|
||||
|
||||
var downstreamContexts = new List<DownstreamContext> { commentsDownstreamContext, userDetailsDownstreamContext };
|
||||
var downstreamContexts = new List<HttpContext> { commentsDownstreamContext, userDetailsDownstreamContext };
|
||||
|
||||
var expected = "{\"Comments\":" + commentsResponseContent + ",\"UserDetails\":" + userDetailsResponseContent + "}";
|
||||
|
||||
this.Given(x => GivenTheUpstreamContext(new DownstreamContext(new DefaultHttpContext())))
|
||||
this.Given(x => GivenTheUpstreamContext(new DefaultHttpContext()))
|
||||
.And(x => GivenTheReRoute(reRoute))
|
||||
.And(x => GivenTheDownstreamContext(downstreamContexts))
|
||||
.When(x => WhenIAggregate())
|
||||
@ -97,23 +94,19 @@ namespace Ocelot.UnitTests.Middleware
|
||||
.WithDownstreamReRoutes(downstreamReRoutes)
|
||||
.Build();
|
||||
|
||||
var billDownstreamContext = new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamResponse = new DownstreamResponse(new StringContent("Bill says hi"), HttpStatusCode.OK, new EditableList<KeyValuePair<string, IEnumerable<string>>>(), "some reason"),
|
||||
DownstreamReRoute = billDownstreamReRoute
|
||||
};
|
||||
var billDownstreamContext = new DefaultHttpContext();
|
||||
billDownstreamContext.Items.UpsertDownstreamResponse(new DownstreamResponse(new StringContent("Bill says hi"), HttpStatusCode.OK, new EditableList<KeyValuePair<string, IEnumerable<string>>>(), "some reason"));
|
||||
billDownstreamContext.Items.UpsertDownstreamReRoute(billDownstreamReRoute);
|
||||
|
||||
var georgeDownstreamContext = new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamResponse = new DownstreamResponse(new StringContent("George says hi"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"),
|
||||
DownstreamReRoute = georgeDownstreamReRoute
|
||||
};
|
||||
var georgeDownstreamContext = new DefaultHttpContext();
|
||||
georgeDownstreamContext.Items.UpsertDownstreamResponse(new DownstreamResponse(new StringContent("George says hi"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"));
|
||||
georgeDownstreamContext.Items.UpsertDownstreamReRoute(georgeDownstreamReRoute);
|
||||
|
||||
var downstreamContexts = new List<DownstreamContext> { billDownstreamContext, georgeDownstreamContext };
|
||||
var downstreamContexts = new List<HttpContext> { billDownstreamContext, georgeDownstreamContext };
|
||||
|
||||
var expected = "{\"Bill\":Bill says hi,\"George\":George says hi}";
|
||||
|
||||
this.Given(x => GivenTheUpstreamContext(new DownstreamContext(new DefaultHttpContext())))
|
||||
this.Given(x => GivenTheUpstreamContext(new DefaultHttpContext()))
|
||||
.And(x => GivenTheReRoute(reRoute))
|
||||
.And(x => GivenTheDownstreamContext(downstreamContexts))
|
||||
.When(x => WhenIAggregate())
|
||||
@ -140,25 +133,21 @@ namespace Ocelot.UnitTests.Middleware
|
||||
.WithDownstreamReRoutes(downstreamReRoutes)
|
||||
.Build();
|
||||
|
||||
var billDownstreamContext = new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamResponse = new DownstreamResponse(new StringContent("Bill says hi"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"),
|
||||
DownstreamReRoute = billDownstreamReRoute
|
||||
};
|
||||
var billDownstreamContext = new DefaultHttpContext();
|
||||
billDownstreamContext.Items.UpsertDownstreamResponse(new DownstreamResponse(new StringContent("Bill says hi"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"));
|
||||
billDownstreamContext.Items.UpsertDownstreamReRoute(billDownstreamReRoute);
|
||||
|
||||
var georgeDownstreamContext = new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamResponse = new DownstreamResponse(new StringContent("Error"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"),
|
||||
DownstreamReRoute = georgeDownstreamReRoute,
|
||||
};
|
||||
var georgeDownstreamContext = new DefaultHttpContext();
|
||||
georgeDownstreamContext.Items.UpsertDownstreamResponse(new DownstreamResponse(new StringContent("Error"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"));
|
||||
georgeDownstreamContext.Items.UpsertDownstreamReRoute(georgeDownstreamReRoute);
|
||||
|
||||
georgeDownstreamContext.Errors.Add(new AnyError());
|
||||
georgeDownstreamContext.Items.SetError(new AnyError());
|
||||
|
||||
var downstreamContexts = new List<DownstreamContext> { billDownstreamContext, georgeDownstreamContext };
|
||||
var downstreamContexts = new List<HttpContext> { billDownstreamContext, georgeDownstreamContext };
|
||||
|
||||
var expected = "Error";
|
||||
|
||||
this.Given(x => GivenTheUpstreamContext(new DownstreamContext(new DefaultHttpContext())))
|
||||
this.Given(x => GivenTheUpstreamContext(new DefaultHttpContext()))
|
||||
.And(x => GivenTheReRoute(reRoute))
|
||||
.And(x => GivenTheDownstreamContext(downstreamContexts))
|
||||
.When(x => WhenIAggregate())
|
||||
@ -169,13 +158,13 @@ namespace Ocelot.UnitTests.Middleware
|
||||
|
||||
private void ThenTheReasonPhraseIs(string expected)
|
||||
{
|
||||
_upstreamContext.DownstreamResponse.ReasonPhrase.ShouldBe(expected);
|
||||
_upstreamContext.Items.DownstreamResponse().ReasonPhrase.ShouldBe(expected);
|
||||
}
|
||||
|
||||
private void ThenTheErrorIsMapped()
|
||||
{
|
||||
_upstreamContext.Errors.ShouldBe(_downstreamContexts[1].Errors);
|
||||
_upstreamContext.DownstreamResponse.ShouldBe(_downstreamContexts[1].DownstreamResponse);
|
||||
_upstreamContext.Items.Errors().ShouldBe(_downstreamContexts[1].Items.Errors());
|
||||
_upstreamContext.Items.DownstreamResponse().ShouldBe(_downstreamContexts[1].Items.DownstreamResponse());
|
||||
}
|
||||
|
||||
private void GivenTheReRoute(ReRoute reRoute)
|
||||
@ -183,12 +172,12 @@ namespace Ocelot.UnitTests.Middleware
|
||||
_reRoute = reRoute;
|
||||
}
|
||||
|
||||
private void GivenTheUpstreamContext(DownstreamContext upstreamContext)
|
||||
private void GivenTheUpstreamContext(HttpContext upstreamContext)
|
||||
{
|
||||
_upstreamContext = upstreamContext;
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamContext(List<DownstreamContext> downstreamContexts)
|
||||
private void GivenTheDownstreamContext(List<HttpContext> downstreamContexts)
|
||||
{
|
||||
_downstreamContexts = downstreamContexts;
|
||||
}
|
||||
@ -200,7 +189,7 @@ namespace Ocelot.UnitTests.Middleware
|
||||
|
||||
private void ThenTheContentIs(string expected)
|
||||
{
|
||||
var content = _upstreamContext.DownstreamResponse.Content.ReadAsStringAsync()
|
||||
var content = _upstreamContext.Items.DownstreamResponse().Content.ReadAsStringAsync()
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
|
||||
@ -209,14 +198,14 @@ namespace Ocelot.UnitTests.Middleware
|
||||
|
||||
private void ThenTheContentTypeIs(string expected)
|
||||
{
|
||||
_upstreamContext.DownstreamResponse.Content.Headers.ContentType.MediaType.ShouldBe(expected);
|
||||
_upstreamContext.Items.DownstreamResponse().Content.Headers.ContentType.MediaType.ShouldBe(expected);
|
||||
}
|
||||
|
||||
private void ThenTheUpstreamContextIsMappedForNonAggregate()
|
||||
{
|
||||
_upstreamContext.DownstreamRequest.ShouldBe(_downstreamContexts[0].DownstreamRequest);
|
||||
_upstreamContext.DownstreamResponse.ShouldBe(_downstreamContexts[0].DownstreamResponse);
|
||||
_upstreamContext.Errors.ShouldBe(_downstreamContexts[0].Errors);
|
||||
_upstreamContext.Items.DownstreamRequest().ShouldBe(_downstreamContexts[0].Items.DownstreamRequest());
|
||||
_upstreamContext.Items.DownstreamRequest().ShouldBe(_downstreamContexts[0].Items.DownstreamRequest());
|
||||
_upstreamContext.Items.Errors().ShouldBe(_downstreamContexts[0].Items.Errors());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,29 +1,29 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Middleware.Multiplexer;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.UnitTests.Responder;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Middleware
|
||||
namespace Ocelot.UnitTests.Multiplexing
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Multiplexer;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.UnitTests.Responder;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class UserDefinedResponseAggregatorTests
|
||||
{
|
||||
private readonly UserDefinedResponseAggregator _aggregator;
|
||||
private readonly Mock<IDefinedAggregatorProvider> _provider;
|
||||
private ReRoute _reRoute;
|
||||
private List<DownstreamContext> _contexts;
|
||||
private DownstreamContext _context;
|
||||
private List<HttpContext> _contexts;
|
||||
private HttpContext _context;
|
||||
|
||||
public UserDefinedResponseAggregatorTests()
|
||||
{
|
||||
@ -36,18 +36,18 @@ namespace Ocelot.UnitTests.Middleware
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().Build();
|
||||
|
||||
var context = new DownstreamContext(new DefaultHttpContext());
|
||||
var context = new DefaultHttpContext();
|
||||
|
||||
var contexts = new List<DownstreamContext>
|
||||
var contextA = new DefaultHttpContext();
|
||||
contextA.Items.UpsertDownstreamResponse(new DownstreamResponse(new StringContent("Tom"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"));
|
||||
|
||||
var contextB = new DefaultHttpContext();
|
||||
contextB.Items.UpsertDownstreamResponse(new DownstreamResponse(new StringContent("Laura"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"));
|
||||
|
||||
var contexts = new List<HttpContext>()
|
||||
{
|
||||
new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamResponse = new DownstreamResponse(new StringContent("Tom"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason")
|
||||
},
|
||||
new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamResponse = new DownstreamResponse(new StringContent("Laura"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason")
|
||||
}
|
||||
contextA,
|
||||
contextB,
|
||||
};
|
||||
|
||||
this.Given(_ => GivenTheProviderReturnsAggregator())
|
||||
@ -65,18 +65,18 @@ namespace Ocelot.UnitTests.Middleware
|
||||
{
|
||||
var reRoute = new ReRouteBuilder().Build();
|
||||
|
||||
var context = new DownstreamContext(new DefaultHttpContext());
|
||||
var context = new DefaultHttpContext();
|
||||
|
||||
var contexts = new List<DownstreamContext>
|
||||
var contextA = new DefaultHttpContext();
|
||||
contextA.Items.UpsertDownstreamResponse(new DownstreamResponse(new StringContent("Tom"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"));
|
||||
|
||||
var contextB = new DefaultHttpContext();
|
||||
contextB.Items.UpsertDownstreamResponse(new DownstreamResponse(new StringContent("Laura"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason"));
|
||||
|
||||
var contexts = new List<HttpContext>()
|
||||
{
|
||||
new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamResponse = new DownstreamResponse(new StringContent("Tom"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason")
|
||||
},
|
||||
new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamResponse = new DownstreamResponse(new StringContent("Laura"), HttpStatusCode.OK, new List<KeyValuePair<string, IEnumerable<string>>>(), "some reason")
|
||||
}
|
||||
contextA,
|
||||
contextB,
|
||||
};
|
||||
|
||||
this.Given(_ => GivenTheProviderReturnsError())
|
||||
@ -91,8 +91,8 @@ namespace Ocelot.UnitTests.Middleware
|
||||
|
||||
private void ThenTheErrorIsReturned()
|
||||
{
|
||||
_context.IsError.ShouldBeTrue();
|
||||
_context.Errors.Count.ShouldBe(1);
|
||||
_context.Items.Errors().Count.ShouldBeGreaterThan(0);
|
||||
_context.Items.Errors().Count.ShouldBe(1);
|
||||
}
|
||||
|
||||
private void GivenTheProviderReturnsError()
|
||||
@ -102,7 +102,7 @@ namespace Ocelot.UnitTests.Middleware
|
||||
|
||||
private async Task ThenTheContentIsCorrect()
|
||||
{
|
||||
var content = await _context.DownstreamResponse.Content.ReadAsStringAsync();
|
||||
var content = await _context.Items.DownstreamResponse().Content.ReadAsStringAsync();
|
||||
content.ShouldBe("Tom, Laura");
|
||||
}
|
||||
|
||||
@ -111,12 +111,12 @@ namespace Ocelot.UnitTests.Middleware
|
||||
_provider.Verify(x => x.Get(_reRoute), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenContext(DownstreamContext context)
|
||||
private void GivenContext(HttpContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
private void GivenContexts(List<DownstreamContext> contexts)
|
||||
private void GivenContexts(List<HttpContext> contexts)
|
||||
{
|
||||
_contexts = contexts;
|
||||
}
|
||||
@ -139,12 +139,12 @@ namespace Ocelot.UnitTests.Middleware
|
||||
|
||||
public class TestDefinedAggregator : IDefinedAggregator
|
||||
{
|
||||
public async Task<DownstreamResponse> Aggregate(List<DownstreamContext> responses)
|
||||
public async Task<DownstreamResponse> Aggregate(List<HttpContext> responses)
|
||||
{
|
||||
var tom = await responses[0].DownstreamResponse.Content.ReadAsStringAsync();
|
||||
var laura = await responses[1].DownstreamResponse.Content.ReadAsStringAsync();
|
||||
var tom = await responses[0].Items.DownstreamResponse().Content.ReadAsStringAsync();
|
||||
var laura = await responses[1].Items.DownstreamResponse().Content.ReadAsStringAsync();
|
||||
var content = $"{tom}, {laura}";
|
||||
var headers = responses.SelectMany(x => x.DownstreamResponse.Headers).ToList();
|
||||
var headers = responses.SelectMany(x => x.Items.DownstreamResponse().Headers).ToList();
|
||||
return new DownstreamResponse(new StringContent(content), HttpStatusCode.OK, headers, "some reason");
|
||||
}
|
||||
}
|
@ -1,194 +1,194 @@
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Infrastructure.Claims.Parser;
|
||||
using Ocelot.QueryStrings;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.QueryStrings
|
||||
{
|
||||
public class AddQueriesToRequestTests
|
||||
{
|
||||
private readonly AddQueriesToRequest _addQueriesToRequest;
|
||||
private DownstreamRequest _downstreamRequest;
|
||||
private readonly Mock<IClaimsParser> _parser;
|
||||
private List<ClaimToThing> _configuration;
|
||||
private List<Claim> _claims;
|
||||
private Response _result;
|
||||
private Response<string> _claimValue;
|
||||
private HttpRequestMessage _request;
|
||||
|
||||
public AddQueriesToRequestTests()
|
||||
{
|
||||
_request = new HttpRequestMessage(HttpMethod.Post, "http://my.url/abc?q=123");
|
||||
_parser = new Mock<IClaimsParser>();
|
||||
_addQueriesToRequest = new AddQueriesToRequest(_parser.Object);
|
||||
_downstreamRequest = new DownstreamRequest(_request);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_new_queries_to_downstream_request()
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim("test", "data")
|
||||
};
|
||||
|
||||
this.Given(
|
||||
x => x.GivenAClaimToThing(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("query-key", "", "", 0)
|
||||
}))
|
||||
.Given(x => x.GivenClaims(claims))
|
||||
.And(x => x.GivenTheClaimParserReturns(new OkResponse<string>("value")))
|
||||
.When(x => x.WhenIAddQueriesToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsSuccess())
|
||||
.And(x => x.ThenTheQueryIsAdded())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_new_queries_to_downstream_request_and_preserve_other_queries()
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim("test", "data")
|
||||
};
|
||||
|
||||
this.Given(
|
||||
x => x.GivenAClaimToThing(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("query-key", "", "", 0)
|
||||
}))
|
||||
.Given(x => x.GivenClaims(claims))
|
||||
.And(x => GivenTheDownstreamRequestHasQueryString("?test=1&test=2"))
|
||||
.And(x => x.GivenTheClaimParserReturns(new OkResponse<string>("value")))
|
||||
.When(x => x.WhenIAddQueriesToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsSuccess())
|
||||
.And(x => x.ThenTheQueryIsAdded())
|
||||
.And(x => TheTheQueryStringIs("?test=1&test=2&query-key=value"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void TheTheQueryStringIs(string expected)
|
||||
{
|
||||
_downstreamRequest.Query.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_replace_existing_queries_on_downstream_request()
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim("test", "data")
|
||||
};
|
||||
|
||||
this.Given(
|
||||
x => x.GivenAClaimToThing(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("query-key", "", "", 0)
|
||||
}))
|
||||
.And(x => x.GivenClaims(claims))
|
||||
.And(x => x.GivenTheDownstreamRequestHasQueryString("query-key", "initial"))
|
||||
.And(x => x.GivenTheClaimParserReturns(new OkResponse<string>("value")))
|
||||
.When(x => x.WhenIAddQueriesToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsSuccess())
|
||||
.And(x => x.ThenTheQueryIsAdded())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error()
|
||||
{
|
||||
this.Given(
|
||||
x => x.GivenAClaimToThing(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("", "", "", 0)
|
||||
}))
|
||||
.Given(x => x.GivenClaims(new List<Claim>()))
|
||||
.And(x => x.GivenTheClaimParserReturns(new ErrorResponse<string>(new List<Error>
|
||||
{
|
||||
new AnyError()
|
||||
})))
|
||||
.When(x => x.WhenIAddQueriesToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsError())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheQueryIsAdded()
|
||||
{
|
||||
var queries = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(_downstreamRequest.ToHttpRequestMessage().RequestUri.OriginalString);
|
||||
var query = queries.First(x => x.Key == "query-key");
|
||||
query.Value.First().ShouldBe(_claimValue.Data);
|
||||
}
|
||||
|
||||
private void GivenAClaimToThing(List<ClaimToThing> configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
private void GivenClaims(List<Claim> claims)
|
||||
{
|
||||
_claims = claims;
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRequestHasQueryString(string queryString)
|
||||
{
|
||||
_request = new HttpRequestMessage(HttpMethod.Post, $"http://my.url/abc{queryString}");
|
||||
_downstreamRequest = new DownstreamRequest(_request);
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRequestHasQueryString(string key, string value)
|
||||
{
|
||||
var newUri = Microsoft.AspNetCore.WebUtilities.QueryHelpers
|
||||
.AddQueryString(_downstreamRequest.ToHttpRequestMessage().RequestUri.OriginalString, key, value);
|
||||
|
||||
_request.RequestUri = new Uri(newUri);
|
||||
}
|
||||
|
||||
private void GivenTheClaimParserReturns(Response<string> claimValue)
|
||||
{
|
||||
_claimValue = claimValue;
|
||||
_parser
|
||||
.Setup(
|
||||
x =>
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Infrastructure.Claims.Parser;
|
||||
using Ocelot.QueryStrings;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.QueryStrings
|
||||
{
|
||||
public class AddQueriesToRequestTests
|
||||
{
|
||||
private readonly AddQueriesToRequest _addQueriesToRequest;
|
||||
private DownstreamRequest _downstreamRequest;
|
||||
private readonly Mock<IClaimsParser> _parser;
|
||||
private List<ClaimToThing> _configuration;
|
||||
private List<Claim> _claims;
|
||||
private Response _result;
|
||||
private Response<string> _claimValue;
|
||||
private HttpRequestMessage _request;
|
||||
|
||||
public AddQueriesToRequestTests()
|
||||
{
|
||||
_request = new HttpRequestMessage(HttpMethod.Post, "http://my.url/abc?q=123");
|
||||
_parser = new Mock<IClaimsParser>();
|
||||
_addQueriesToRequest = new AddQueriesToRequest(_parser.Object);
|
||||
_downstreamRequest = new DownstreamRequest(_request);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_new_queries_to_downstream_request()
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim("test", "data")
|
||||
};
|
||||
|
||||
this.Given(
|
||||
x => x.GivenAClaimToThing(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("query-key", "", "", 0)
|
||||
}))
|
||||
.Given(x => x.GivenClaims(claims))
|
||||
.And(x => x.GivenTheClaimParserReturns(new OkResponse<string>("value")))
|
||||
.When(x => x.WhenIAddQueriesToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsSuccess())
|
||||
.And(x => x.ThenTheQueryIsAdded())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_new_queries_to_downstream_request_and_preserve_other_queries()
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim("test", "data")
|
||||
};
|
||||
|
||||
this.Given(
|
||||
x => x.GivenAClaimToThing(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("query-key", "", "", 0)
|
||||
}))
|
||||
.Given(x => x.GivenClaims(claims))
|
||||
.And(x => GivenTheDownstreamRequestHasQueryString("?test=1&test=2"))
|
||||
.And(x => x.GivenTheClaimParserReturns(new OkResponse<string>("value")))
|
||||
.When(x => x.WhenIAddQueriesToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsSuccess())
|
||||
.And(x => x.ThenTheQueryIsAdded())
|
||||
.And(x => TheTheQueryStringIs("?test=1&test=2&query-key=value"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void TheTheQueryStringIs(string expected)
|
||||
{
|
||||
_downstreamRequest.Query.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_replace_existing_queries_on_downstream_request()
|
||||
{
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim("test", "data")
|
||||
};
|
||||
|
||||
this.Given(
|
||||
x => x.GivenAClaimToThing(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("query-key", "", "", 0)
|
||||
}))
|
||||
.And(x => x.GivenClaims(claims))
|
||||
.And(x => x.GivenTheDownstreamRequestHasQueryString("query-key", "initial"))
|
||||
.And(x => x.GivenTheClaimParserReturns(new OkResponse<string>("value")))
|
||||
.When(x => x.WhenIAddQueriesToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsSuccess())
|
||||
.And(x => x.ThenTheQueryIsAdded())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_error()
|
||||
{
|
||||
this.Given(
|
||||
x => x.GivenAClaimToThing(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("", "", "", 0)
|
||||
}))
|
||||
.Given(x => x.GivenClaims(new List<Claim>()))
|
||||
.And(x => x.GivenTheClaimParserReturns(new ErrorResponse<string>(new List<Error>
|
||||
{
|
||||
new AnyError()
|
||||
})))
|
||||
.When(x => x.WhenIAddQueriesToTheRequest())
|
||||
.Then(x => x.ThenTheResultIsError())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheQueryIsAdded()
|
||||
{
|
||||
var queries = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(_downstreamRequest.ToHttpRequestMessage().RequestUri.OriginalString);
|
||||
var query = queries.First(x => x.Key == "query-key");
|
||||
query.Value.First().ShouldBe(_claimValue.Data);
|
||||
}
|
||||
|
||||
private void GivenAClaimToThing(List<ClaimToThing> configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
private void GivenClaims(List<Claim> claims)
|
||||
{
|
||||
_claims = claims;
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRequestHasQueryString(string queryString)
|
||||
{
|
||||
_request = new HttpRequestMessage(HttpMethod.Post, $"http://my.url/abc{queryString}");
|
||||
_downstreamRequest = new DownstreamRequest(_request);
|
||||
}
|
||||
|
||||
private void GivenTheDownstreamRequestHasQueryString(string key, string value)
|
||||
{
|
||||
var newUri = Microsoft.AspNetCore.WebUtilities.QueryHelpers
|
||||
.AddQueryString(_downstreamRequest.ToHttpRequestMessage().RequestUri.OriginalString, key, value);
|
||||
|
||||
_request.RequestUri = new Uri(newUri);
|
||||
}
|
||||
|
||||
private void GivenTheClaimParserReturns(Response<string> claimValue)
|
||||
{
|
||||
_claimValue = claimValue;
|
||||
_parser
|
||||
.Setup(
|
||||
x =>
|
||||
x.GetValue(It.IsAny<IEnumerable<Claim>>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<int>()))
|
||||
.Returns(_claimValue);
|
||||
}
|
||||
|
||||
private void WhenIAddQueriesToTheRequest()
|
||||
{
|
||||
_result = _addQueriesToRequest.SetQueriesOnDownstreamRequest(_configuration, _claims, _downstreamRequest);
|
||||
}
|
||||
|
||||
private void ThenTheResultIsSuccess()
|
||||
{
|
||||
_result.IsError.ShouldBe(false);
|
||||
}
|
||||
|
||||
private void ThenTheResultIsError()
|
||||
{
|
||||
_result.IsError.ShouldBe(true);
|
||||
}
|
||||
|
||||
private class AnyError : Error
|
||||
{
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<int>()))
|
||||
.Returns(_claimValue);
|
||||
}
|
||||
|
||||
private void WhenIAddQueriesToTheRequest()
|
||||
{
|
||||
_result = _addQueriesToRequest.SetQueriesOnDownstreamRequest(_configuration, _claims, _downstreamRequest);
|
||||
}
|
||||
|
||||
private void ThenTheResultIsSuccess()
|
||||
{
|
||||
_result.IsError.ShouldBe(false);
|
||||
}
|
||||
|
||||
private void ThenTheResultIsError()
|
||||
{
|
||||
_result.IsError.ShouldBe(true);
|
||||
}
|
||||
|
||||
private class AnyError : Error
|
||||
{
|
||||
public AnyError()
|
||||
: base("blahh", OcelotErrorCode.UnknownError)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
: base("blahh", OcelotErrorCode.UnknownError, 404)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,97 +1,102 @@
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.QueryStrings
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.QueryStrings;
|
||||
using Ocelot.QueryStrings.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.QueryStrings
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.QueryStrings;
|
||||
using Ocelot.QueryStrings.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class ClaimsToQueryStringMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IAddQueriesToRequest> _addQueries;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private ClaimsToQueryStringMiddleware _middleware;
|
||||
private DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
|
||||
public ClaimsToQueryStringMiddlewareTests()
|
||||
{
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ClaimsToQueryStringMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
public class ClaimsToQueryStringMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IAddQueriesToRequest> _addQueries;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private ClaimsToQueryStringMiddleware _middleware;
|
||||
private RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
private Mock<IRequestScopedDataRepository> _repo;
|
||||
|
||||
public ClaimsToQueryStringMiddlewareTests()
|
||||
{
|
||||
_repo = new Mock<IRequestScopedDataRepository>();
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ClaimsToQueryStringMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_addQueries = new Mock<IAddQueriesToRequest>();
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com"));
|
||||
_middleware = new ClaimsToQueryStringMiddleware(_next, _loggerFactory.Object, _addQueries.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_add_queries_correctly()
|
||||
_httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com")));
|
||||
_middleware = new ClaimsToQueryStringMiddleware(_next, _loggerFactory.Object, _addQueries.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_add_queries_correctly()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithClaimsToQueries(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("UserId", "Subject", "", 0)
|
||||
})
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => x.GivenTheAddHeadersToRequestReturnsOk())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheAddQueriesToRequestIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheAddHeadersToRequestReturnsOk()
|
||||
{
|
||||
_addQueries
|
||||
.Setup(x => x.SetQueriesOnDownstreamRequest(
|
||||
It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<IEnumerable<Claim>>(),
|
||||
It.IsAny<DownstreamRequest>()))
|
||||
.Returns(new OkResponse());
|
||||
}
|
||||
|
||||
private void ThenTheAddQueriesToRequestIsCalledCorrectly()
|
||||
{
|
||||
_addQueries
|
||||
.Verify(x => x.SetQueriesOnDownstreamRequest(
|
||||
It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<IEnumerable<Claim>>(),
|
||||
_httpContext.Items.DownstreamRequest()), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithClaimsToQueries(new List<ClaimToThing>
|
||||
{
|
||||
new ClaimToThing("UserId", "Subject", "", 0)
|
||||
})
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
_httpContext.Items.UpsertTemplatePlaceholderNameAndValues(downstreamRoute.TemplatePlaceholderNameAndValues);
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => x.GivenTheAddHeadersToRequestReturnsOk())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheAddQueriesToRequestIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheAddHeadersToRequestReturnsOk()
|
||||
{
|
||||
_addQueries
|
||||
.Setup(x => x.SetQueriesOnDownstreamRequest(
|
||||
It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<IEnumerable<Claim>>(),
|
||||
It.IsAny<DownstreamRequest>()))
|
||||
.Returns(new OkResponse());
|
||||
}
|
||||
|
||||
private void ThenTheAddQueriesToRequestIsCalledCorrectly()
|
||||
{
|
||||
_addQueries
|
||||
.Verify(x => x.SetQueriesOnDownstreamRequest(
|
||||
It.IsAny<List<ClaimToThing>>(),
|
||||
It.IsAny<IEnumerable<Claim>>(),
|
||||
_downstreamContext.DownstreamRequest), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
|
||||
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
_httpContext.Items.UpsertDownstreamReRoute(downstreamRoute.ReRoute.DownstreamReRoute[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,179 +1,186 @@
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.RateLimit
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.RateLimit;
|
||||
using Ocelot.RateLimit.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class ClientRateLimitMiddlewareTests
|
||||
{
|
||||
private int _responseStatusCode;
|
||||
private IRateLimitCounterHandler _rateLimitCounterHandler;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly ClientRateLimitMiddleware _middleware;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
private readonly string _url;
|
||||
|
||||
public ClientRateLimitMiddlewareTests()
|
||||
{
|
||||
_url = "http://localhost:51879";
|
||||
var cacheEntryOptions = new MemoryCacheOptions();
|
||||
_rateLimitCounterHandler = new MemoryCacheRateLimitCounterHandler(new MemoryCache(cacheEntryOptions));
|
||||
var httpContext = new DefaultHttpContext();
|
||||
_downstreamContext = new DownstreamContext(httpContext);
|
||||
_downstreamContext.HttpContext.Response.Body = new FakeStream();
|
||||
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ClientRateLimitMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new ClientRateLimitMiddleware(_next, _loggerFactory.Object, _rateLimitCounterHandler);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_middleware_and_ratelimiting()
|
||||
{
|
||||
var upstreamTemplate = new UpstreamPathTemplateBuilder().Build();
|
||||
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithEnableRateLimiting(true)
|
||||
.WithRateLimitOptions(new RateLimitOptions(true, "ClientId", () => new List<string>(), false, "", "", new RateLimitRule("1s", 100, 3), 429))
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithUpstreamPathTemplate(upstreamTemplate)
|
||||
.Build();
|
||||
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(), reRoute);
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.When(x => x.WhenICallTheMiddlewareMultipleTime(2))
|
||||
.Then(x => x.ThenresponseStatusCodeIs200())
|
||||
.When(x => x.WhenICallTheMiddlewareMultipleTime(3))
|
||||
.Then(x => x.ThenresponseStatusCodeIs429())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_middleware_withWhitelistClient()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithEnableRateLimiting(true)
|
||||
.WithRateLimitOptions(
|
||||
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", () => new List<string>() { "ocelotclient2" }, false, "", "", new RateLimitRule("1s", 100, 3), 429))
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.When(x => x.WhenICallTheMiddlewareWithWhiteClient())
|
||||
.Then(x => x.ThenresponseStatusCodeIs200())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
|
||||
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddlewareMultipleTime(int times)
|
||||
{
|
||||
var clientId = "ocelotclient1";
|
||||
|
||||
for (int i = 0; i < times; i++)
|
||||
{
|
||||
var request = new HttpRequestMessage(new HttpMethod("GET"), _url);
|
||||
request.Headers.Add("ClientId", clientId);
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(request);
|
||||
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
_responseStatusCode = (int)_downstreamContext.HttpContext.Response.StatusCode;
|
||||
}
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddlewareWithWhiteClient()
|
||||
{
|
||||
var clientId = "ocelotclient2";
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var request = new HttpRequestMessage(new HttpMethod("GET"), _url);
|
||||
request.Headers.Add("ClientId", clientId);
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(request);
|
||||
_downstreamContext.HttpContext.Request.Headers.TryAdd("ClientId", clientId);
|
||||
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
_responseStatusCode = (int)_downstreamContext.HttpContext.Response.StatusCode;
|
||||
}
|
||||
}
|
||||
|
||||
private void ThenresponseStatusCodeIs429()
|
||||
{
|
||||
_responseStatusCode.ShouldBe(429);
|
||||
}
|
||||
|
||||
private void ThenresponseStatusCodeIs200()
|
||||
{
|
||||
_responseStatusCode.ShouldBe(200);
|
||||
}
|
||||
}
|
||||
|
||||
internal class FakeStream : Stream
|
||||
{
|
||||
public override void Flush()
|
||||
{
|
||||
//do nothing
|
||||
//throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
|
||||
public override bool CanRead { get; }
|
||||
public override bool CanSeek { get; }
|
||||
public override bool CanWrite => true;
|
||||
public override long Length { get; }
|
||||
public override long Position { get; set; }
|
||||
}
|
||||
}
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.RateLimit
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.RateLimit;
|
||||
using Ocelot.RateLimit.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Shouldly;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class ClientRateLimitMiddlewareTests
|
||||
{
|
||||
private int _responseStatusCode;
|
||||
private IRateLimitCounterHandler _rateLimitCounterHandler;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly ClientRateLimitMiddleware _middleware;
|
||||
private RequestDelegate _next;
|
||||
private DownstreamResponse _downstreamResponse;
|
||||
private readonly string _url;
|
||||
|
||||
public ClientRateLimitMiddlewareTests()
|
||||
{
|
||||
_url = "http://localhost:51879";
|
||||
var cacheEntryOptions = new MemoryCacheOptions();
|
||||
_rateLimitCounterHandler = new MemoryCacheRateLimitCounterHandler(new MemoryCache(cacheEntryOptions));
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ClientRateLimitMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new ClientRateLimitMiddleware(_next, _loggerFactory.Object, _rateLimitCounterHandler);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_middleware_and_ratelimiting()
|
||||
{
|
||||
var upstreamTemplate = new UpstreamPathTemplateBuilder().Build();
|
||||
|
||||
var downstreamReRoute = new DownstreamReRouteBuilder()
|
||||
.WithEnableRateLimiting(true)
|
||||
.WithRateLimitOptions(new RateLimitOptions(true, "ClientId", () => new List<string>(), false, "", "", new RateLimitRule("1s", 100, 3), 429))
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.WithUpstreamPathTemplate(upstreamTemplate)
|
||||
.Build();
|
||||
|
||||
var reRoute = new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(downstreamReRoute)
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build();
|
||||
|
||||
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(), reRoute);
|
||||
|
||||
this.Given(x => x.WhenICallTheMiddlewareMultipleTimes(2, downstreamRoute))
|
||||
.Then(x => x.ThenThereIsNoDownstreamResponse())
|
||||
.When(x => x.WhenICallTheMiddlewareMultipleTimes(3, downstreamRoute))
|
||||
.Then(x => x.ThenTheResponseIs429())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_middleware_withWhitelistClient()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithEnableRateLimiting(true)
|
||||
.WithRateLimitOptions(
|
||||
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", () => new List<string>() { "ocelotclient2" }, false, "", "", new RateLimitRule("1s", 100, 3), 429))
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
this.Given(x => x.WhenICallTheMiddlewareWithWhiteClient(downstreamRoute))
|
||||
.Then(x => x.ThenThereIsNoDownstreamResponse())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddlewareMultipleTimes(int times, DownstreamRoute downstreamRoute)
|
||||
{
|
||||
var httpContexts = new List<HttpContext>();
|
||||
|
||||
for (int i = 0; i < times; i++)
|
||||
{
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Response.Body = new FakeStream();
|
||||
httpContext.Items.UpsertDownstreamReRoute(downstreamRoute.ReRoute.DownstreamReRoute[0]);
|
||||
httpContext.Items.UpsertTemplatePlaceholderNameAndValues(downstreamRoute.TemplatePlaceholderNameAndValues);
|
||||
httpContext.Items.UpsertDownstreamRoute(downstreamRoute);
|
||||
var clientId = "ocelotclient1";
|
||||
var request = new HttpRequestMessage(new HttpMethod("GET"), _url);
|
||||
httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(request));
|
||||
httpContext.Request.Headers.TryAdd("ClientId", clientId);
|
||||
httpContexts.Add(httpContext);
|
||||
}
|
||||
|
||||
foreach (var httpContext in httpContexts)
|
||||
{
|
||||
_middleware.Invoke(httpContext).GetAwaiter().GetResult();
|
||||
var ds = httpContext.Items.DownstreamResponse();
|
||||
_downstreamResponse = ds;
|
||||
}
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddlewareWithWhiteClient(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
var clientId = "ocelotclient2";
|
||||
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Response.Body = new FakeStream();
|
||||
httpContext.Items.UpsertDownstreamReRoute(downstreamRoute.ReRoute.DownstreamReRoute[0]);
|
||||
httpContext.Items.UpsertTemplatePlaceholderNameAndValues(downstreamRoute.TemplatePlaceholderNameAndValues);
|
||||
httpContext.Items.UpsertDownstreamRoute(downstreamRoute);
|
||||
var request = new HttpRequestMessage(new HttpMethod("GET"), _url);
|
||||
request.Headers.Add("ClientId", clientId);
|
||||
httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(request));
|
||||
httpContext.Request.Headers.TryAdd("ClientId", clientId);
|
||||
_middleware.Invoke(httpContext).GetAwaiter().GetResult();
|
||||
var ds = httpContext.Items.DownstreamResponse();
|
||||
_downstreamResponse = ds;
|
||||
}
|
||||
}
|
||||
|
||||
private void ThenTheResponseIs429()
|
||||
{
|
||||
var code = (int)_downstreamResponse.StatusCode;
|
||||
code.ShouldBe(429);
|
||||
}
|
||||
|
||||
private void ThenThereIsNoDownstreamResponse()
|
||||
{
|
||||
_downstreamResponse.ShouldBeNull();
|
||||
}
|
||||
}
|
||||
|
||||
internal class FakeStream : Stream
|
||||
{
|
||||
public override void Flush()
|
||||
{
|
||||
//do nothing
|
||||
//throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override void SetLength(long value)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count)
|
||||
{
|
||||
//do nothing
|
||||
}
|
||||
|
||||
public override bool CanRead { get; }
|
||||
public override bool CanSeek { get; }
|
||||
public override bool CanWrite => true;
|
||||
public override long Length { get; }
|
||||
public override long Position { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -15,32 +15,23 @@
|
||||
using Ocelot.Configuration;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class DownstreamRequestInitialiserMiddlewareTests
|
||||
{
|
||||
private readonly DownstreamRequestInitialiserMiddleware _middleware;
|
||||
|
||||
private readonly Mock<HttpContext> _httpContext;
|
||||
|
||||
private readonly Mock<HttpRequest> _httpRequest;
|
||||
|
||||
private readonly Mock<OcelotRequestDelegate> _next;
|
||||
|
||||
private readonly HttpContext _httpContext;
|
||||
private readonly Mock<RequestDelegate> _next;
|
||||
private readonly Mock<IRequestMapper> _requestMapper;
|
||||
|
||||
private readonly Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
|
||||
private readonly Mock<IOcelotLogger> _logger;
|
||||
|
||||
private Response<HttpRequestMessage> _mappedRequest;
|
||||
private DownstreamContext _downstreamContext;
|
||||
|
||||
public DownstreamRequestInitialiserMiddlewareTests()
|
||||
{
|
||||
_httpContext = new Mock<HttpContext>();
|
||||
_httpRequest = new Mock<HttpRequest>();
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_requestMapper = new Mock<IRequestMapper>();
|
||||
_next = new Mock<OcelotRequestDelegate>();
|
||||
_next = new Mock<RequestDelegate>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
@ -53,8 +44,6 @@
|
||||
_loggerFactory.Object,
|
||||
_requestMapper.Object,
|
||||
new DownstreamRequestCreator(new FrameworkDescription()));
|
||||
|
||||
_downstreamContext = new DownstreamContext(_httpContext.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@ -97,14 +86,12 @@
|
||||
|
||||
private void ThenTheDownstreamRequestMethodIs(string expected)
|
||||
{
|
||||
_downstreamContext.DownstreamRequest.Method.ShouldBe(expected);
|
||||
_httpContext.Items.DownstreamRequest().Method.ShouldBe(expected);
|
||||
}
|
||||
|
||||
private void GivenTheHttpContextContainsARequest()
|
||||
{
|
||||
_httpContext
|
||||
.Setup(hc => hc.Request)
|
||||
.Returns(_httpRequest.Object);
|
||||
_httpContext.Items.UpsertDownstreamReRoute(new DownstreamReRouteBuilder().Build());
|
||||
}
|
||||
|
||||
private void GivenTheMapperWillReturnAMappedRequest()
|
||||
@ -127,38 +114,38 @@
|
||||
|
||||
private void WhenTheMiddlewareIsInvoked()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThenTheContexRequestIsMappedToADownstreamRequest()
|
||||
{
|
||||
_requestMapper.Verify(rm => rm.Map(_httpRequest.Object, _downstreamContext.DownstreamReRoute), Times.Once);
|
||||
_requestMapper.Verify(rm => rm.Map(_httpContext.Request, _httpContext.Items.DownstreamReRoute()), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamRequestIsStored()
|
||||
{
|
||||
_downstreamContext.DownstreamRequest.ShouldNotBeNull();
|
||||
_httpContext.Items.DownstreamRequest().ShouldNotBeNull();
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamRequestIsNotStored()
|
||||
{
|
||||
_downstreamContext.DownstreamRequest.ShouldBeNull();
|
||||
_httpContext.Items.DownstreamRequest().ShouldBeNull();
|
||||
}
|
||||
|
||||
private void ThenAPipelineErrorIsStored()
|
||||
{
|
||||
_downstreamContext.IsError.ShouldBeTrue();
|
||||
_downstreamContext.Errors.ShouldBe(_mappedRequest.Errors);
|
||||
_httpContext.Items.Errors().Count.ShouldBeGreaterThan(0);
|
||||
_httpContext.Items.Errors().ShouldBe(_mappedRequest.Errors);
|
||||
}
|
||||
|
||||
private void ThenTheNextMiddlewareIsInvoked()
|
||||
{
|
||||
_next.Verify(n => n(_downstreamContext), Times.Once);
|
||||
_next.Verify(n => n(_httpContext), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheNextMiddlewareIsNotInvoked()
|
||||
{
|
||||
_next.Verify(n => n(It.IsAny<DownstreamContext>()), Times.Never);
|
||||
_next.Verify(n => n(It.IsAny<HttpContext>()), Times.Never);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,222 +1,223 @@
|
||||
namespace Ocelot.UnitTests.RequestId
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.RequestId.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class ReRouteRequestIdMiddlewareTests
|
||||
{
|
||||
private readonly HttpRequestMessage _downstreamRequest;
|
||||
private string _value;
|
||||
private string _key;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly ReRouteRequestIdMiddleware _middleware;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
private readonly Mock<IRequestScopedDataRepository> _repo;
|
||||
|
||||
public ReRouteRequestIdMiddlewareTests()
|
||||
{
|
||||
_downstreamRequest = new HttpRequestMessage(HttpMethod.Get, "http://test.com");
|
||||
_repo = new Mock<IRequestScopedDataRepository>();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ReRouteRequestIdMiddleware>()).Returns(_logger.Object);
|
||||
_next = context =>
|
||||
{
|
||||
context.HttpContext.Response.Headers.Add("LSRequestId", context.HttpContext.TraceIdentifier);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
_middleware = new ReRouteRequestIdMiddleware(_next, _loggerFactory.Object, _repo.Object);
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(_downstreamRequest);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_pass_down_request_id_from_upstream_request()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithRequestIdKey("LSRequestId")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var requestId = Guid.NewGuid().ToString();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenThereIsNoGlobalRequestId())
|
||||
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheTraceIdIs(requestId))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_request_id_when_not_on_upstream_request()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithRequestIdKey("LSRequestId")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenThereIsNoGlobalRequestId())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheTraceIdIsAnything())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_request_id_scoped_repo_for_logging_later()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithRequestIdKey("LSRequestId")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var requestId = Guid.NewGuid().ToString();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenThereIsNoGlobalRequestId())
|
||||
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheTraceIdIs(requestId))
|
||||
.And(x => ThenTheRequestIdIsSaved())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_update_request_id_scoped_repo_for_logging_later()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithRequestIdKey("LSRequestId")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var requestId = Guid.NewGuid().ToString();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheRequestIdWasSetGlobally())
|
||||
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheTraceIdIs(requestId))
|
||||
.And(x => ThenTheRequestIdIsUpdated())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_update_if_global_request_id_is_same_as_re_route_request_id()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithRequestIdKey("LSRequestId")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var requestId = "alreadyset";
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheRequestIdWasSetGlobally())
|
||||
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheTraceIdIs(requestId))
|
||||
.And(x => ThenTheRequestIdIsNotUpdated())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenThereIsNoGlobalRequestId()
|
||||
{
|
||||
_repo.Setup(x => x.Get<string>("RequestId")).Returns(new OkResponse<string>(null));
|
||||
}
|
||||
|
||||
private void GivenTheRequestIdWasSetGlobally()
|
||||
{
|
||||
_repo.Setup(x => x.Get<string>("RequestId")).Returns(new OkResponse<string>("alreadyset"));
|
||||
}
|
||||
|
||||
private void ThenTheRequestIdIsSaved()
|
||||
{
|
||||
_repo.Verify(x => x.Add("RequestId", _value), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheRequestIdIsUpdated()
|
||||
{
|
||||
_repo.Verify(x => x.Update("RequestId", _value), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheRequestIdIsNotUpdated()
|
||||
{
|
||||
_repo.Verify(x => x.Update("RequestId", _value), Times.Never);
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
|
||||
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
|
||||
}
|
||||
|
||||
private void GivenTheRequestIdIsAddedToTheRequest(string key, string value)
|
||||
{
|
||||
_key = key;
|
||||
_value = value;
|
||||
_downstreamContext.HttpContext.Request.Headers.TryAdd(_key, _value);
|
||||
}
|
||||
|
||||
private void ThenTheTraceIdIsAnything()
|
||||
{
|
||||
_downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out var value);
|
||||
value.First().ShouldNotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
private void ThenTheTraceIdIs(string expected)
|
||||
{
|
||||
_downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out var value);
|
||||
value.First().ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
namespace Ocelot.UnitTests.RequestId
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.RequestId.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class ReRouteRequestIdMiddlewareTests
|
||||
{
|
||||
private readonly HttpRequestMessage _downstreamRequest;
|
||||
private string _value;
|
||||
private string _key;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly ReRouteRequestIdMiddleware _middleware;
|
||||
private RequestDelegate _next;
|
||||
private readonly Mock<IRequestScopedDataRepository> _repo;
|
||||
private HttpContext _httpContext;
|
||||
public ReRouteRequestIdMiddlewareTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_downstreamRequest = new HttpRequestMessage(HttpMethod.Get, "http://test.com");
|
||||
_repo = new Mock<IRequestScopedDataRepository>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ReRouteRequestIdMiddleware>()).Returns(_logger.Object);
|
||||
_next = context =>
|
||||
{
|
||||
_httpContext.Response.Headers.Add("LSRequestId", _httpContext.TraceIdentifier);
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
_middleware = new ReRouteRequestIdMiddleware(_next, _loggerFactory.Object, _repo.Object);
|
||||
_httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(_downstreamRequest));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_pass_down_request_id_from_upstream_request()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithRequestIdKey("LSRequestId")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var requestId = Guid.NewGuid().ToString();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenThereIsNoGlobalRequestId())
|
||||
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheTraceIdIs(requestId))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_request_id_when_not_on_upstream_request()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithRequestIdKey("LSRequestId")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenThereIsNoGlobalRequestId())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheTraceIdIsAnything())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_add_request_id_scoped_repo_for_logging_later()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithRequestIdKey("LSRequestId")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var requestId = Guid.NewGuid().ToString();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenThereIsNoGlobalRequestId())
|
||||
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheTraceIdIs(requestId))
|
||||
.And(x => ThenTheRequestIdIsSaved())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_update_request_id_scoped_repo_for_logging_later()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithRequestIdKey("LSRequestId")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var requestId = Guid.NewGuid().ToString();
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheRequestIdWasSetGlobally())
|
||||
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheTraceIdIs(requestId))
|
||||
.And(x => ThenTheRequestIdIsUpdated())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_update_if_global_request_id_is_same_as_re_route_request_id()
|
||||
{
|
||||
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
|
||||
new ReRouteBuilder()
|
||||
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
|
||||
.WithDownstreamPathTemplate("any old string")
|
||||
.WithRequestIdKey("LSRequestId")
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build())
|
||||
.WithUpstreamHttpMethod(new List<string> { "Get" })
|
||||
.Build());
|
||||
|
||||
var requestId = "alreadyset";
|
||||
|
||||
this.Given(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
|
||||
.And(x => GivenTheRequestIdWasSetGlobally())
|
||||
.And(x => x.GivenTheRequestIdIsAddedToTheRequest("LSRequestId", requestId))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheTraceIdIs(requestId))
|
||||
.And(x => ThenTheRequestIdIsNotUpdated())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenThereIsNoGlobalRequestId()
|
||||
{
|
||||
_repo.Setup(x => x.Get<string>("RequestId")).Returns(new OkResponse<string>(null));
|
||||
}
|
||||
|
||||
private void GivenTheRequestIdWasSetGlobally()
|
||||
{
|
||||
_repo.Setup(x => x.Get<string>("RequestId")).Returns(new OkResponse<string>("alreadyset"));
|
||||
}
|
||||
|
||||
private void ThenTheRequestIdIsSaved()
|
||||
{
|
||||
_repo.Verify(x => x.Add("RequestId", _value), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheRequestIdIsUpdated()
|
||||
{
|
||||
_repo.Verify(x => x.Update("RequestId", _value), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheRequestIdIsNotUpdated()
|
||||
{
|
||||
_repo.Verify(x => x.Update("RequestId", _value), Times.Never);
|
||||
}
|
||||
|
||||
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
|
||||
{
|
||||
_httpContext.Items.UpsertTemplatePlaceholderNameAndValues(downstreamRoute.TemplatePlaceholderNameAndValues);
|
||||
|
||||
_httpContext.Items.UpsertDownstreamReRoute(downstreamRoute.ReRoute.DownstreamReRoute[0]);
|
||||
}
|
||||
|
||||
private void GivenTheRequestIdIsAddedToTheRequest(string key, string value)
|
||||
{
|
||||
_key = key;
|
||||
_value = value;
|
||||
_httpContext.Request.Headers.TryAdd(_key, _value);
|
||||
}
|
||||
|
||||
private void ThenTheTraceIdIsAnything()
|
||||
{
|
||||
_httpContext.Response.Headers.TryGetValue("LSRequestId", out var value);
|
||||
value.First().ShouldNotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
private void ThenTheTraceIdIs(string expected)
|
||||
{
|
||||
_httpContext.Response.Headers.TryGetValue("LSRequestId", out var value);
|
||||
value.First().ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,449 +1,446 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Requester;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Requester
|
||||
{
|
||||
public class HttpClientBuilderTests : IDisposable
|
||||
{
|
||||
private HttpClientBuilder _builder;
|
||||
private readonly Mock<IDelegatingHandlerHandlerFactory> _factory;
|
||||
private IHttpClient _httpClient;
|
||||
private HttpResponseMessage _response;
|
||||
private DownstreamContext _context;
|
||||
private readonly Mock<IHttpClientCache> _cacheHandlers;
|
||||
private readonly Mock<IOcelotLogger> _logger;
|
||||
private int _count;
|
||||
private IWebHost _host;
|
||||
private IHttpClient _againHttpClient;
|
||||
private IHttpClient _firstHttpClient;
|
||||
private MemoryHttpClientCache _realCache;
|
||||
|
||||
public HttpClientBuilderTests()
|
||||
{
|
||||
_cacheHandlers = new Mock<IHttpClientCache>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_factory = new Mock<IDelegatingHandlerHandlerFactory>();
|
||||
_builder = new HttpClientBuilder(_factory.Object, _cacheHandlers.Object, _logger.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_build_http_client()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFactoryReturns())
|
||||
.And(x => GivenARequest(reRoute))
|
||||
.When(x => WhenIBuild())
|
||||
.Then(x => ThenTheHttpClientShouldNotBeNull())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_get_from_cache()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenARealCache())
|
||||
.And(x => GivenTheFactoryReturns())
|
||||
.And(x => GivenARequest(reRoute))
|
||||
.And(x => WhenIBuildTheFirstTime())
|
||||
.And(x => WhenISave())
|
||||
.And(x => WhenIBuildAgain())
|
||||
.And(x => WhenISave())
|
||||
.When(x => WhenIBuildAgain())
|
||||
.Then(x => ThenTheHttpClientIsFromTheCache())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_get_from_cache_with_different_query_string()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenARealCache())
|
||||
.And(x => GivenTheFactoryReturns())
|
||||
.And(x => GivenARequest(reRoute, "http://wwww.someawesomewebsite.com/woot?badman=1"))
|
||||
.And(x => WhenIBuildTheFirstTime())
|
||||
.And(x => WhenISave())
|
||||
.And(x => WhenIBuildAgain())
|
||||
.And(x => GivenARequest(reRoute, "http://wwww.someawesomewebsite.com/woot?badman=2"))
|
||||
.And(x => WhenISave())
|
||||
.When(x => WhenIBuildAgain())
|
||||
.Then(x => ThenTheHttpClientIsFromTheCache())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_get_from_cache_with_different_query_string()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRouteA = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithContainsQueryString(true).WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
var reRouteB = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithContainsQueryString(true).WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenARealCache())
|
||||
.And(x => GivenTheFactoryReturns())
|
||||
.And(x => GivenARequest(reRouteA, "http://wwww.someawesomewebsite.com/woot?badman=1"))
|
||||
.And(x => WhenIBuildTheFirstTime())
|
||||
.And(x => WhenISave())
|
||||
.And(x => WhenIBuildAgain())
|
||||
.And(x => GivenARequest(reRouteB, "http://wwww.someawesomewebsite.com/woot?badman=2"))
|
||||
.And(x => WhenISave())
|
||||
.When(x => WhenIBuildAgain())
|
||||
.Then(x => ThenTheHttpClientIsNotFromTheCache())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_log_if_ignoring_ssl_errors()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.WithDangerousAcceptAnyServerCertificateValidator(true)
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFactoryReturns())
|
||||
.And(x => GivenARequest(reRoute))
|
||||
.When(x => WhenIBuild())
|
||||
.Then(x => ThenTheHttpClientShouldNotBeNull())
|
||||
.Then(x => ThenTheDangerousAcceptAnyServerCertificateValidatorWarningIsLogged())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_delegating_handlers_in_order()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
var fakeOne = new FakeDelegatingHandler();
|
||||
var fakeTwo = new FakeDelegatingHandler();
|
||||
|
||||
var handlers = new List<Func<DelegatingHandler>>()
|
||||
{
|
||||
() => fakeOne,
|
||||
() => fakeTwo
|
||||
};
|
||||
|
||||
this.Given(x => GivenTheFactoryReturns(handlers))
|
||||
.And(x => GivenARequest(reRoute))
|
||||
.And(x => WhenIBuild())
|
||||
.When(x => WhenICallTheClient())
|
||||
.Then(x => ThenTheFakeAreHandledInOrder(fakeOne, fakeTwo))
|
||||
.And(x => ThenSomethingIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_re_use_cookies_from_container()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, true, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(_ => GivenADownstreamService())
|
||||
.And(_ => GivenARequest(reRoute))
|
||||
.And(_ => GivenTheFactoryReturnsNothing())
|
||||
.And(_ => WhenIBuild())
|
||||
.And(_ => WhenICallTheClient("http://localhost:5003"))
|
||||
.And(_ => ThenTheCookieIsSet())
|
||||
.And(_ => GivenTheClientIsCached())
|
||||
.And(_ => WhenIBuild())
|
||||
.When(_ => WhenICallTheClient("http://localhost:5003"))
|
||||
.Then(_ => ThenTheResponseIsOk())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET")]
|
||||
[InlineData("POST")]
|
||||
[InlineData("PUT")]
|
||||
[InlineData("DELETE")]
|
||||
[InlineData("PATCH")]
|
||||
public void should_add_verb_to_cache_key(string verb)
|
||||
{
|
||||
var downstreamUrl = "http://localhost:5012/";
|
||||
|
||||
var method = new HttpMethod(verb);
|
||||
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(_ => GivenADownstreamService())
|
||||
.And(_ => GivenARequestWithAUrlAndMethod(reRoute, downstreamUrl, method))
|
||||
.And(_ => GivenTheFactoryReturnsNothing())
|
||||
.And(_ => WhenIBuild())
|
||||
.And(_ => GivenCacheIsCalledWithExpectedKey($"{method.ToString()}:{downstreamUrl}"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenARealCache()
|
||||
{
|
||||
_realCache = new MemoryHttpClientCache();
|
||||
_builder = new HttpClientBuilder(_factory.Object, _realCache, _logger.Object);
|
||||
}
|
||||
|
||||
private void ThenTheHttpClientIsFromTheCache()
|
||||
{
|
||||
_againHttpClient.ShouldBe(_firstHttpClient);
|
||||
}
|
||||
|
||||
private void ThenTheHttpClientIsNotFromTheCache()
|
||||
{
|
||||
_againHttpClient.ShouldNotBe(_firstHttpClient);
|
||||
}
|
||||
|
||||
private void WhenISave()
|
||||
{
|
||||
_builder.Save();
|
||||
}
|
||||
|
||||
private void GivenCacheIsCalledWithExpectedKey(string expectedKey)
|
||||
{
|
||||
_cacheHandlers.Verify(x => x.Get(It.IsAny<DownstreamReRoute>()), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheDangerousAcceptAnyServerCertificateValidatorWarningIsLogged()
|
||||
{
|
||||
_logger.Verify(x => x.LogWarning($"You have ignored all SSL warnings by using DangerousAcceptAnyServerCertificateValidator for this DownstreamReRoute, UpstreamPathTemplate: {_context.DownstreamReRoute.UpstreamPathTemplate}, DownstreamPathTemplate: {_context.DownstreamReRoute.DownstreamPathTemplate}"), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheClientIsCached()
|
||||
{
|
||||
_cacheHandlers.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(_httpClient);
|
||||
}
|
||||
|
||||
private void ThenTheCookieIsSet()
|
||||
{
|
||||
_response.Headers.TryGetValues("Set-Cookie", out var test).ShouldBeTrue();
|
||||
}
|
||||
|
||||
private void WhenICallTheClient(string url)
|
||||
{
|
||||
_response = _httpClient
|
||||
.SendAsync(new HttpRequestMessage(HttpMethod.Get, url))
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
}
|
||||
|
||||
private void ThenTheResponseIsOk()
|
||||
{
|
||||
_response.StatusCode.ShouldBe(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
private void GivenADownstreamService()
|
||||
{
|
||||
_host = new WebHostBuilder()
|
||||
.UseUrls("http://localhost:5003")
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(context =>
|
||||
{
|
||||
if (_count == 0)
|
||||
{
|
||||
context.Response.Cookies.Append("test", "0");
|
||||
context.Response.StatusCode = 200;
|
||||
_count++;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (_count == 1)
|
||||
{
|
||||
if (context.Request.Cookies.TryGetValue("test", out var cookieValue) || context.Request.Headers.TryGetValue("Set-Cookie", out var headerValue))
|
||||
{
|
||||
context.Response.StatusCode = 200;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
context.Response.StatusCode = 500;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_host.Start();
|
||||
}
|
||||
|
||||
private void GivenARequest(DownstreamReRoute downstream)
|
||||
{
|
||||
GivenARequest(downstream, "http://localhost:5003");
|
||||
}
|
||||
|
||||
private void GivenARequest(DownstreamReRoute downstream, string downstreamUrl)
|
||||
{
|
||||
GivenARequestWithAUrlAndMethod(downstream, downstreamUrl, HttpMethod.Get);
|
||||
}
|
||||
|
||||
private void GivenARequestWithAUrlAndMethod(DownstreamReRoute downstream, string url, HttpMethod method)
|
||||
{
|
||||
var context = new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamReRoute = downstream,
|
||||
DownstreamRequest = new DownstreamRequest(new HttpRequestMessage() { RequestUri = new Uri(url), Method = method }),
|
||||
};
|
||||
|
||||
_context = context;
|
||||
}
|
||||
|
||||
private void ThenSomethingIsReturned()
|
||||
{
|
||||
_response.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
private void WhenICallTheClient()
|
||||
{
|
||||
_response = _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, "http://test.com")).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThenTheFakeAreHandledInOrder(FakeDelegatingHandler fakeOne, FakeDelegatingHandler fakeTwo)
|
||||
{
|
||||
fakeOne.TimeCalled.ShouldBeGreaterThan(fakeTwo.TimeCalled);
|
||||
}
|
||||
|
||||
private void GivenTheFactoryReturns()
|
||||
{
|
||||
var handlers = new List<Func<DelegatingHandler>>() { () => new FakeDelegatingHandler() };
|
||||
|
||||
_factory
|
||||
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
|
||||
.Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
|
||||
}
|
||||
|
||||
private void GivenTheFactoryReturnsNothing()
|
||||
{
|
||||
var handlers = new List<Func<DelegatingHandler>>();
|
||||
|
||||
_factory
|
||||
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
|
||||
.Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
|
||||
}
|
||||
|
||||
private void GivenTheFactoryReturns(List<Func<DelegatingHandler>> handlers)
|
||||
{
|
||||
_factory
|
||||
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
|
||||
.Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
|
||||
}
|
||||
|
||||
private void WhenIBuild()
|
||||
{
|
||||
_httpClient = _builder.Create(_context);
|
||||
}
|
||||
|
||||
private void WhenIBuildTheFirstTime()
|
||||
{
|
||||
_firstHttpClient = _builder.Create(_context);
|
||||
}
|
||||
|
||||
private void WhenIBuildAgain()
|
||||
{
|
||||
_builder = new HttpClientBuilder(_factory.Object, _realCache, _logger.Object);
|
||||
_againHttpClient = _builder.Create(_context);
|
||||
}
|
||||
|
||||
private void ThenTheHttpClientShouldNotBeNull()
|
||||
{
|
||||
_httpClient.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_response?.Dispose();
|
||||
_host?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Requester;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Requester
|
||||
{
|
||||
public class HttpClientBuilderTests : IDisposable
|
||||
{
|
||||
private HttpClientBuilder _builder;
|
||||
private readonly Mock<IDelegatingHandlerHandlerFactory> _factory;
|
||||
private IHttpClient _httpClient;
|
||||
private HttpResponseMessage _response;
|
||||
private HttpContext _context;
|
||||
private readonly Mock<IHttpClientCache> _cacheHandlers;
|
||||
private readonly Mock<IOcelotLogger> _logger;
|
||||
private int _count;
|
||||
private IWebHost _host;
|
||||
private IHttpClient _againHttpClient;
|
||||
private IHttpClient _firstHttpClient;
|
||||
private MemoryHttpClientCache _realCache;
|
||||
|
||||
public HttpClientBuilderTests()
|
||||
{
|
||||
_cacheHandlers = new Mock<IHttpClientCache>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_factory = new Mock<IDelegatingHandlerHandlerFactory>();
|
||||
_builder = new HttpClientBuilder(_factory.Object, _cacheHandlers.Object, _logger.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_build_http_client()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFactoryReturns())
|
||||
.And(x => GivenARequest(reRoute))
|
||||
.When(x => WhenIBuild())
|
||||
.Then(x => ThenTheHttpClientShouldNotBeNull())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_get_from_cache()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenARealCache())
|
||||
.And(x => GivenTheFactoryReturns())
|
||||
.And(x => GivenARequest(reRoute))
|
||||
.And(x => WhenIBuildTheFirstTime())
|
||||
.And(x => WhenISave())
|
||||
.And(x => WhenIBuildAgain())
|
||||
.And(x => WhenISave())
|
||||
.When(x => WhenIBuildAgain())
|
||||
.Then(x => ThenTheHttpClientIsFromTheCache())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_get_from_cache_with_different_query_string()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenARealCache())
|
||||
.And(x => GivenTheFactoryReturns())
|
||||
.And(x => GivenARequest(reRoute, "http://wwww.someawesomewebsite.com/woot?badman=1"))
|
||||
.And(x => WhenIBuildTheFirstTime())
|
||||
.And(x => WhenISave())
|
||||
.And(x => WhenIBuildAgain())
|
||||
.And(x => GivenARequest(reRoute, "http://wwww.someawesomewebsite.com/woot?badman=2"))
|
||||
.And(x => WhenISave())
|
||||
.When(x => WhenIBuildAgain())
|
||||
.Then(x => ThenTheHttpClientIsFromTheCache())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_get_from_cache_with_different_query_string()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRouteA = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithContainsQueryString(true).WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
var reRouteB = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithContainsQueryString(true).WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenARealCache())
|
||||
.And(x => GivenTheFactoryReturns())
|
||||
.And(x => GivenARequest(reRouteA, "http://wwww.someawesomewebsite.com/woot?badman=1"))
|
||||
.And(x => WhenIBuildTheFirstTime())
|
||||
.And(x => WhenISave())
|
||||
.And(x => WhenIBuildAgain())
|
||||
.And(x => GivenARequest(reRouteB, "http://wwww.someawesomewebsite.com/woot?badman=2"))
|
||||
.And(x => WhenISave())
|
||||
.When(x => WhenIBuildAgain())
|
||||
.Then(x => ThenTheHttpClientIsNotFromTheCache())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_log_if_ignoring_ssl_errors()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.WithDangerousAcceptAnyServerCertificateValidator(true)
|
||||
.Build();
|
||||
|
||||
this.Given(x => GivenTheFactoryReturns())
|
||||
.And(x => GivenARequest(reRoute))
|
||||
.When(x => WhenIBuild())
|
||||
.Then(x => ThenTheHttpClientShouldNotBeNull())
|
||||
.Then(x => ThenTheDangerousAcceptAnyServerCertificateValidatorWarningIsLogged())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_delegating_handlers_in_order()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
var fakeOne = new FakeDelegatingHandler();
|
||||
var fakeTwo = new FakeDelegatingHandler();
|
||||
|
||||
var handlers = new List<Func<DelegatingHandler>>()
|
||||
{
|
||||
() => fakeOne,
|
||||
() => fakeTwo
|
||||
};
|
||||
|
||||
this.Given(x => GivenTheFactoryReturns(handlers))
|
||||
.And(x => GivenARequest(reRoute))
|
||||
.And(x => WhenIBuild())
|
||||
.When(x => WhenICallTheClient())
|
||||
.Then(x => ThenTheFakeAreHandledInOrder(fakeOne, fakeTwo))
|
||||
.And(x => ThenSomethingIsReturned())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_re_use_cookies_from_container()
|
||||
{
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, true, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(_ => GivenADownstreamService())
|
||||
.And(_ => GivenARequest(reRoute))
|
||||
.And(_ => GivenTheFactoryReturnsNothing())
|
||||
.And(_ => WhenIBuild())
|
||||
.And(_ => WhenICallTheClient("http://localhost:5003"))
|
||||
.And(_ => ThenTheCookieIsSet())
|
||||
.And(_ => GivenTheClientIsCached())
|
||||
.And(_ => WhenIBuild())
|
||||
.When(_ => WhenICallTheClient("http://localhost:5003"))
|
||||
.Then(_ => ThenTheResponseIsOk())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET")]
|
||||
[InlineData("POST")]
|
||||
[InlineData("PUT")]
|
||||
[InlineData("DELETE")]
|
||||
[InlineData("PATCH")]
|
||||
public void should_add_verb_to_cache_key(string verb)
|
||||
{
|
||||
var downstreamUrl = "http://localhost:5012/";
|
||||
|
||||
var method = new HttpMethod(verb);
|
||||
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(new UpstreamPathTemplateBuilder().WithOriginalValue("").Build())
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
this.Given(_ => GivenADownstreamService())
|
||||
.And(_ => GivenARequestWithAUrlAndMethod(reRoute, downstreamUrl, method))
|
||||
.And(_ => GivenTheFactoryReturnsNothing())
|
||||
.And(_ => WhenIBuild())
|
||||
.And(_ => GivenCacheIsCalledWithExpectedKey($"{method.ToString()}:{downstreamUrl}"))
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenARealCache()
|
||||
{
|
||||
_realCache = new MemoryHttpClientCache();
|
||||
_builder = new HttpClientBuilder(_factory.Object, _realCache, _logger.Object);
|
||||
}
|
||||
|
||||
private void ThenTheHttpClientIsFromTheCache()
|
||||
{
|
||||
_againHttpClient.ShouldBe(_firstHttpClient);
|
||||
}
|
||||
|
||||
private void ThenTheHttpClientIsNotFromTheCache()
|
||||
{
|
||||
_againHttpClient.ShouldNotBe(_firstHttpClient);
|
||||
}
|
||||
|
||||
private void WhenISave()
|
||||
{
|
||||
_builder.Save();
|
||||
}
|
||||
|
||||
private void GivenCacheIsCalledWithExpectedKey(string expectedKey)
|
||||
{
|
||||
_cacheHandlers.Verify(x => x.Get(It.IsAny<DownstreamReRoute>()), Times.Once);
|
||||
}
|
||||
|
||||
private void ThenTheDangerousAcceptAnyServerCertificateValidatorWarningIsLogged()
|
||||
{
|
||||
_logger.Verify(x => x.LogWarning($"You have ignored all SSL warnings by using DangerousAcceptAnyServerCertificateValidator for this DownstreamReRoute, UpstreamPathTemplate: {_context.Items.DownstreamReRoute().UpstreamPathTemplate}, DownstreamPathTemplate: {_context.Items.DownstreamReRoute().DownstreamPathTemplate}"), Times.Once);
|
||||
}
|
||||
|
||||
private void GivenTheClientIsCached()
|
||||
{
|
||||
_cacheHandlers.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(_httpClient);
|
||||
}
|
||||
|
||||
private void ThenTheCookieIsSet()
|
||||
{
|
||||
_response.Headers.TryGetValues("Set-Cookie", out var test).ShouldBeTrue();
|
||||
}
|
||||
|
||||
private void WhenICallTheClient(string url)
|
||||
{
|
||||
_response = _httpClient
|
||||
.SendAsync(new HttpRequestMessage(HttpMethod.Get, url))
|
||||
.GetAwaiter()
|
||||
.GetResult();
|
||||
}
|
||||
|
||||
private void ThenTheResponseIsOk()
|
||||
{
|
||||
_response.StatusCode.ShouldBe(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
private void GivenADownstreamService()
|
||||
{
|
||||
_host = new WebHostBuilder()
|
||||
.UseUrls("http://localhost:5003")
|
||||
.UseKestrel()
|
||||
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||
.UseIISIntegration()
|
||||
.Configure(app =>
|
||||
{
|
||||
app.Run(context =>
|
||||
{
|
||||
if (_count == 0)
|
||||
{
|
||||
context.Response.Cookies.Append("test", "0");
|
||||
context.Response.StatusCode = 200;
|
||||
_count++;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
if (_count == 1)
|
||||
{
|
||||
if (context.Request.Cookies.TryGetValue("test", out var cookieValue) || context.Request.Headers.TryGetValue("Set-Cookie", out var headerValue))
|
||||
{
|
||||
context.Response.StatusCode = 200;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
context.Response.StatusCode = 500;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
})
|
||||
.Build();
|
||||
|
||||
_host.Start();
|
||||
}
|
||||
|
||||
private void GivenARequest(DownstreamReRoute downstream)
|
||||
{
|
||||
GivenARequest(downstream, "http://localhost:5003");
|
||||
}
|
||||
|
||||
private void GivenARequest(DownstreamReRoute downstream, string downstreamUrl)
|
||||
{
|
||||
GivenARequestWithAUrlAndMethod(downstream, downstreamUrl, HttpMethod.Get);
|
||||
}
|
||||
|
||||
private void GivenARequestWithAUrlAndMethod(DownstreamReRoute downstream, string url, HttpMethod method)
|
||||
{
|
||||
_context = new DefaultHttpContext();
|
||||
_context.Items.UpsertDownstreamReRoute(downstream);
|
||||
_context.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage() { RequestUri = new Uri(url), Method = method }));
|
||||
}
|
||||
|
||||
private void ThenSomethingIsReturned()
|
||||
{
|
||||
_response.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
private void WhenICallTheClient()
|
||||
{
|
||||
_response = _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, "http://test.com")).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThenTheFakeAreHandledInOrder(FakeDelegatingHandler fakeOne, FakeDelegatingHandler fakeTwo)
|
||||
{
|
||||
fakeOne.TimeCalled.ShouldBeGreaterThan(fakeTwo.TimeCalled);
|
||||
}
|
||||
|
||||
private void GivenTheFactoryReturns()
|
||||
{
|
||||
var handlers = new List<Func<DelegatingHandler>>() { () => new FakeDelegatingHandler() };
|
||||
|
||||
_factory
|
||||
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
|
||||
.Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
|
||||
}
|
||||
|
||||
private void GivenTheFactoryReturnsNothing()
|
||||
{
|
||||
var handlers = new List<Func<DelegatingHandler>>();
|
||||
|
||||
_factory
|
||||
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
|
||||
.Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
|
||||
}
|
||||
|
||||
private void GivenTheFactoryReturns(List<Func<DelegatingHandler>> handlers)
|
||||
{
|
||||
_factory
|
||||
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
|
||||
.Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
|
||||
}
|
||||
|
||||
private void WhenIBuild()
|
||||
{
|
||||
_httpClient = _builder.Create(_context.Items.DownstreamReRoute());
|
||||
}
|
||||
|
||||
private void WhenIBuildTheFirstTime()
|
||||
{
|
||||
_firstHttpClient = _builder.Create(_context.Items.DownstreamReRoute());
|
||||
}
|
||||
|
||||
private void WhenIBuildAgain()
|
||||
{
|
||||
_builder = new HttpClientBuilder(_factory.Object, _realCache, _logger.Object);
|
||||
_againHttpClient = _builder.Create(_context.Items.DownstreamReRoute());
|
||||
}
|
||||
|
||||
private void ThenTheHttpClientShouldNotBeNull()
|
||||
{
|
||||
_httpClient.ShouldNotBeNull();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_response?.Dispose();
|
||||
_host?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,202 +1,198 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Requester;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Requester;
|
||||
using Ocelot.Responses;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Requester
|
||||
{
|
||||
public class HttpClientHttpRequesterTest
|
||||
{
|
||||
private readonly Mock<IHttpClientCache> _cacheHandlers;
|
||||
private readonly Mock<IDelegatingHandlerHandlerFactory> _factory;
|
||||
private Response<HttpResponseMessage> _response;
|
||||
private readonly HttpClientHttpRequester _httpClientRequester;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private Mock<IExceptionToErrorMapper> _mapper;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public HttpClientHttpRequesterTest()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_factory = new Mock<IDelegatingHandlerHandlerFactory>();
|
||||
_factory.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(new OkResponse<List<Func<DelegatingHandler>>>(new List<Func<DelegatingHandler>>()));
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_loggerFactory
|
||||
.Setup(x => x.CreateLogger<HttpClientHttpRequester>())
|
||||
.Returns(_logger.Object);
|
||||
_cacheHandlers = new Mock<IHttpClientCache>();
|
||||
_mapper = new Mock<IExceptionToErrorMapper>();
|
||||
_httpClientRequester = new HttpClientHttpRequester(
|
||||
_loggerFactory.Object,
|
||||
_cacheHandlers.Object,
|
||||
_factory.Object,
|
||||
_mapper.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_request_correctly()
|
||||
{
|
||||
var upstreamTemplate = new UpstreamPathTemplateBuilder().WithOriginalValue("").Build();
|
||||
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(upstreamTemplate)
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
namespace Ocelot.UnitTests.Requester
|
||||
{
|
||||
public class HttpClientHttpRequesterTest
|
||||
{
|
||||
private readonly Mock<IHttpClientCache> _cacheHandlers;
|
||||
private readonly Mock<IDelegatingHandlerHandlerFactory> _factory;
|
||||
private Response<HttpResponseMessage> _response;
|
||||
private readonly HttpClientHttpRequester _httpClientRequester;
|
||||
private DownstreamContext _request;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private Mock<IExceptionToErrorMapper> _mapper;
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Items.UpsertDownstreamReRoute(reRoute);
|
||||
httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage() { RequestUri = new Uri("http://www.bbc.co.uk") }));
|
||||
|
||||
public HttpClientHttpRequesterTest()
|
||||
{
|
||||
_factory = new Mock<IDelegatingHandlerHandlerFactory>();
|
||||
_factory.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(new OkResponse<List<Func<DelegatingHandler>>>(new List<Func<DelegatingHandler>>()));
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_loggerFactory
|
||||
.Setup(x => x.CreateLogger<HttpClientHttpRequester>())
|
||||
.Returns(_logger.Object);
|
||||
_cacheHandlers = new Mock<IHttpClientCache>();
|
||||
_mapper = new Mock<IExceptionToErrorMapper>();
|
||||
_httpClientRequester = new HttpClientHttpRequester(
|
||||
_loggerFactory.Object,
|
||||
_cacheHandlers.Object,
|
||||
_factory.Object,
|
||||
_mapper.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_request_correctly()
|
||||
{
|
||||
var upstreamTemplate = new UpstreamPathTemplateBuilder().WithOriginalValue("").Build();
|
||||
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
this.Given(x => x.GivenTheRequestIs(httpContext))
|
||||
.And(x => GivenTheHouseReturnsOkHandler())
|
||||
.When(x => x.WhenIGetResponse())
|
||||
.Then(x => x.ThenTheResponseIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_request_unable_to_complete_request()
|
||||
{
|
||||
var upstreamTemplate = new UpstreamPathTemplateBuilder().WithOriginalValue("").Build();
|
||||
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(upstreamTemplate)
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(upstreamTemplate)
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Items.UpsertDownstreamReRoute(reRoute);
|
||||
httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage() { RequestUri = new Uri("http://localhost:60080") }));
|
||||
|
||||
this.Given(x => x.GivenTheRequestIs(httpContext))
|
||||
.When(x => x.WhenIGetResponse())
|
||||
.Then(x => x.ThenTheResponseIsCalledError())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void http_client_request_times_out()
|
||||
{
|
||||
var upstreamTemplate = new UpstreamPathTemplateBuilder().WithOriginalValue("").Build();
|
||||
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(upstreamTemplate)
|
||||
.WithQosOptions(new QoSOptionsBuilder().WithTimeoutValue(1).Build())
|
||||
.Build();
|
||||
|
||||
var context = new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamReRoute = reRoute,
|
||||
DownstreamRequest = new DownstreamRequest(new HttpRequestMessage() { RequestUri = new Uri("http://www.bbc.co.uk") }),
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenTheRequestIs(context))
|
||||
.And(x => GivenTheHouseReturnsOkHandler())
|
||||
.When(x => x.WhenIGetResponse())
|
||||
.Then(x => x.ThenTheResponseIsCalledCorrectly())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_request_unable_to_complete_request()
|
||||
{
|
||||
var upstreamTemplate = new UpstreamPathTemplateBuilder().WithOriginalValue("").Build();
|
||||
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(upstreamTemplate)
|
||||
.WithQosOptions(new QoSOptionsBuilder().Build())
|
||||
.Build();
|
||||
|
||||
var context = new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamReRoute = reRoute,
|
||||
DownstreamRequest = new DownstreamRequest(new HttpRequestMessage() { RequestUri = new Uri("http://localhost:60080") }),
|
||||
};
|
||||
|
||||
this.Given(x => x.GivenTheRequestIs(context))
|
||||
.When(x => x.WhenIGetResponse())
|
||||
.Then(x => x.ThenTheResponseIsCalledError())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void http_client_request_times_out()
|
||||
{
|
||||
var upstreamTemplate = new UpstreamPathTemplateBuilder().WithOriginalValue("").Build();
|
||||
|
||||
var qosOptions = new QoSOptionsBuilder()
|
||||
.Build();
|
||||
|
||||
var reRoute = new DownstreamReRouteBuilder()
|
||||
.WithQosOptions(qosOptions)
|
||||
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false, true, int.MaxValue))
|
||||
.WithLoadBalancerKey("")
|
||||
.WithUpstreamPathTemplate(upstreamTemplate)
|
||||
.WithQosOptions(new QoSOptionsBuilder().WithTimeoutValue(1).Build())
|
||||
.Build();
|
||||
|
||||
var context = new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamReRoute = reRoute,
|
||||
DownstreamRequest = new DownstreamRequest(new HttpRequestMessage() { RequestUri = new Uri("http://localhost:60080") }),
|
||||
};
|
||||
|
||||
this.Given(_ => GivenTheRequestIs(context))
|
||||
.And(_ => GivenTheHouseReturnsTimeoutHandler())
|
||||
.When(_ => WhenIGetResponse())
|
||||
.Then(_ => ThenTheResponseIsCalledError())
|
||||
.And(_ => ThenTheErrorIsTimeout())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheRequestIs(DownstreamContext request)
|
||||
{
|
||||
_request = request;
|
||||
}
|
||||
|
||||
private void WhenIGetResponse()
|
||||
{
|
||||
_response = _httpClientRequester.GetResponse(_request).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThenTheResponseIsCalledCorrectly()
|
||||
{
|
||||
_response.IsError.ShouldBeFalse();
|
||||
}
|
||||
|
||||
private void ThenTheResponseIsCalledError()
|
||||
{
|
||||
_response.IsError.ShouldBeTrue();
|
||||
}
|
||||
|
||||
private void ThenTheErrorIsTimeout()
|
||||
{
|
||||
_mapper.Verify(x => x.Map(It.IsAny<Exception>()), Times.Once);
|
||||
_response.Errors[0].ShouldBeOfType<UnableToCompleteRequestError>();
|
||||
}
|
||||
|
||||
private void GivenTheHouseReturnsOkHandler()
|
||||
{
|
||||
var handlers = new List<Func<DelegatingHandler>>
|
||||
{
|
||||
() => new OkDelegatingHandler()
|
||||
};
|
||||
|
||||
_factory.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
|
||||
}
|
||||
|
||||
private void GivenTheHouseReturnsTimeoutHandler()
|
||||
{
|
||||
var handlers = new List<Func<DelegatingHandler>>
|
||||
{
|
||||
() => new TimeoutDelegatingHandler()
|
||||
};
|
||||
|
||||
_factory.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
|
||||
|
||||
_mapper.Setup(x => x.Map(It.IsAny<Exception>())).Returns(new UnableToCompleteRequestError(new Exception()));
|
||||
}
|
||||
|
||||
private class OkDelegatingHandler : DelegatingHandler
|
||||
{
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(new HttpResponseMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private class TimeoutDelegatingHandler : DelegatingHandler
|
||||
{
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
await Task.Delay(100000, cancellationToken);
|
||||
return new HttpResponseMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Items.UpsertDownstreamReRoute(reRoute);
|
||||
httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage() { RequestUri = new Uri("http://localhost:60080") }));
|
||||
|
||||
this.Given(_ => GivenTheRequestIs(httpContext))
|
||||
.And(_ => GivenTheHouseReturnsTimeoutHandler())
|
||||
.When(_ => WhenIGetResponse())
|
||||
.Then(_ => ThenTheResponseIsCalledError())
|
||||
.And(_ => ThenTheErrorIsTimeout())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenTheRequestIs(HttpContext httpContext)
|
||||
{
|
||||
_httpContext = httpContext;
|
||||
}
|
||||
|
||||
private void WhenIGetResponse()
|
||||
{
|
||||
_response = _httpClientRequester.GetResponse(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThenTheResponseIsCalledCorrectly()
|
||||
{
|
||||
_response.IsError.ShouldBeFalse();
|
||||
}
|
||||
|
||||
private void ThenTheResponseIsCalledError()
|
||||
{
|
||||
_response.IsError.ShouldBeTrue();
|
||||
}
|
||||
|
||||
private void ThenTheErrorIsTimeout()
|
||||
{
|
||||
_mapper.Verify(x => x.Map(It.IsAny<Exception>()), Times.Once);
|
||||
_response.Errors[0].ShouldBeOfType<UnableToCompleteRequestError>();
|
||||
}
|
||||
|
||||
private void GivenTheHouseReturnsOkHandler()
|
||||
{
|
||||
var handlers = new List<Func<DelegatingHandler>>
|
||||
{
|
||||
() => new OkDelegatingHandler()
|
||||
};
|
||||
|
||||
_factory.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
|
||||
}
|
||||
|
||||
private void GivenTheHouseReturnsTimeoutHandler()
|
||||
{
|
||||
var handlers = new List<Func<DelegatingHandler>>
|
||||
{
|
||||
() => new TimeoutDelegatingHandler()
|
||||
};
|
||||
|
||||
_factory.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
|
||||
|
||||
_mapper.Setup(x => x.Map(It.IsAny<Exception>())).Returns(new UnableToCompleteRequestError(new Exception()));
|
||||
}
|
||||
|
||||
private class OkDelegatingHandler : DelegatingHandler
|
||||
{
|
||||
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(new HttpResponseMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private class TimeoutDelegatingHandler : DelegatingHandler
|
||||
{
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
await Task.Delay(100000, cancellationToken);
|
||||
return new HttpResponseMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,132 +1,132 @@
|
||||
namespace Ocelot.UnitTests.Requester
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Requester;
|
||||
using Ocelot.Requester.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.UnitTests.Responder;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
namespace Ocelot.UnitTests.Requester
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Requester;
|
||||
using Ocelot.Requester.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.UnitTests.Responder;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class HttpRequesterMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IHttpRequester> _requester;
|
||||
private Response<HttpResponseMessage> _response;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly HttpRequesterMiddleware _middleware;
|
||||
private DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
|
||||
public HttpRequesterMiddlewareTests()
|
||||
public class HttpRequesterMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IHttpRequester> _requester;
|
||||
private Response<HttpResponseMessage> _response;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly HttpRequesterMiddleware _middleware;
|
||||
private RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public HttpRequesterMiddlewareTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_requester = new Mock<IHttpRequester>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<HttpRequesterMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new HttpRequesterMiddleware(_next, _loggerFactory.Object, _requester.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_services_correctly()
|
||||
{
|
||||
this.Given(x => x.GivenTheRequestIs())
|
||||
.And(x => x.GivenTheRequesterReturns(new OkResponse<HttpResponseMessage>(new HttpResponseMessage(System.Net.HttpStatusCode.OK))))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamResponseIsSet())
|
||||
.Then(x => InformationIsLogged())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_error()
|
||||
{
|
||||
this.Given(x => x.GivenTheRequestIs())
|
||||
.And(x => x.GivenTheRequesterReturns(new ErrorResponse<HttpResponseMessage>(new AnyError())))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheErrorIsSet())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_log_downstream_internal_server_error()
|
||||
{
|
||||
this.Given(x => x.GivenTheRequestIs())
|
||||
.And(x => x.GivenTheRequesterReturns(
|
||||
new OkResponse<HttpResponseMessage>(new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError))))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.WarningIsLogged())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheErrorIsSet()
|
||||
{
|
||||
_httpContext.Items.Errors().Count.ShouldBeGreaterThan(0);
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheRequestIs()
|
||||
{
|
||||
_requester = new Mock<IHttpRequester>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<HttpRequesterMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new HttpRequesterMiddleware(_next, _loggerFactory.Object, _requester.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_call_services_correctly()
|
||||
{
|
||||
this.Given(x => x.GivenTheRequestIs())
|
||||
.And(x => x.GivenTheRequesterReturns(new OkResponse<HttpResponseMessage>(new HttpResponseMessage(System.Net.HttpStatusCode.OK))))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheDownstreamResponseIsSet())
|
||||
.Then(x => InformationIsLogged())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_set_error()
|
||||
{
|
||||
this.Given(x => x.GivenTheRequestIs())
|
||||
.And(x => x.GivenTheRequesterReturns(new ErrorResponse<HttpResponseMessage>(new AnyError())))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheErrorIsSet())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_log_downstream_internal_server_error()
|
||||
{
|
||||
this.Given(x => x.GivenTheRequestIs())
|
||||
.And(x => x.GivenTheRequesterReturns(
|
||||
new OkResponse<HttpResponseMessage>(new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError))))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.WarningIsLogged())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void ThenTheErrorIsSet()
|
||||
{
|
||||
_downstreamContext.IsError.ShouldBeTrue();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheRequestIs()
|
||||
{
|
||||
_downstreamContext =
|
||||
new DownstreamContext(new DefaultHttpContext())
|
||||
{
|
||||
DownstreamReRoute = new DownstreamReRouteBuilder().Build()
|
||||
};
|
||||
}
|
||||
|
||||
private void GivenTheRequesterReturns(Response<HttpResponseMessage> response)
|
||||
{
|
||||
_response = response;
|
||||
|
||||
_requester
|
||||
.Setup(x => x.GetResponse(It.IsAny<DownstreamContext>()))
|
||||
.ReturnsAsync(_response);
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamResponseIsSet()
|
||||
{
|
||||
foreach (var httpResponseHeader in _response.Data.Headers)
|
||||
{
|
||||
if (_downstreamContext.DownstreamResponse.Headers.Any(x => x.Key == httpResponseHeader.Key))
|
||||
{
|
||||
throw new Exception("Header in response not in downstreamresponse headers");
|
||||
}
|
||||
}
|
||||
|
||||
_downstreamContext.DownstreamResponse.Content.ShouldBe(_response.Data.Content);
|
||||
_downstreamContext.DownstreamResponse.StatusCode.ShouldBe(_response.Data.StatusCode);
|
||||
}
|
||||
|
||||
private void WarningIsLogged()
|
||||
{
|
||||
_logger.Verify(
|
||||
x => x.LogWarning(
|
||||
It.IsAny<string>()
|
||||
),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
private void InformationIsLogged()
|
||||
{
|
||||
_logger.Verify(
|
||||
x => x.LogInformation(
|
||||
It.IsAny<string>()
|
||||
),
|
||||
Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
_httpContext.Items.UpsertDownstreamReRoute(new DownstreamReRouteBuilder().Build());
|
||||
}
|
||||
|
||||
private void GivenTheRequesterReturns(Response<HttpResponseMessage> response)
|
||||
{
|
||||
_response = response;
|
||||
|
||||
_requester
|
||||
.Setup(x => x.GetResponse(It.IsAny<HttpContext>()))
|
||||
.ReturnsAsync(_response);
|
||||
}
|
||||
|
||||
private void ThenTheDownstreamResponseIsSet()
|
||||
{
|
||||
foreach (var httpResponseHeader in _response.Data.Headers)
|
||||
{
|
||||
if (_httpContext.Items.DownstreamResponse().Headers.Any(x => x.Key == httpResponseHeader.Key))
|
||||
{
|
||||
throw new Exception("Header in response not in downstreamresponse headers");
|
||||
}
|
||||
}
|
||||
|
||||
_httpContext.Items.DownstreamResponse().Content.ShouldBe(_response.Data.Content);
|
||||
_httpContext.Items.DownstreamResponse().StatusCode.ShouldBe(_response.Data.StatusCode);
|
||||
}
|
||||
|
||||
private void WarningIsLogged()
|
||||
{
|
||||
_logger.Verify(
|
||||
x => x.LogWarning(
|
||||
It.IsAny<string>()
|
||||
),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
private void InformationIsLogged()
|
||||
{
|
||||
_logger.Verify(
|
||||
x => x.LogInformation(
|
||||
It.IsAny<string>()
|
||||
),
|
||||
Times.Once);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
using Ocelot.Errors;
|
||||
|
||||
namespace Ocelot.UnitTests.Responder
|
||||
{
|
||||
internal class AnyError : Error
|
||||
{
|
||||
public AnyError() : base("blahh", OcelotErrorCode.UnknownError)
|
||||
{
|
||||
}
|
||||
|
||||
public AnyError(OcelotErrorCode errorCode) : base("blah", errorCode)
|
||||
{
|
||||
}
|
||||
}
|
||||
using Ocelot.Errors;
|
||||
|
||||
namespace Ocelot.UnitTests.Responder
|
||||
{
|
||||
internal class AnyError : Error
|
||||
{
|
||||
public AnyError() : base("blahh", OcelotErrorCode.UnknownError, 404)
|
||||
{
|
||||
}
|
||||
|
||||
public AnyError(OcelotErrorCode errorCode) : base("blah", errorCode, 404)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,78 +1,80 @@
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.Responder
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.DownstreamRouteFinder.Finder;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Responder;
|
||||
using Ocelot.Responder.Middleware;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class ResponderMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IHttpResponder> _responder;
|
||||
private readonly Mock<IErrorsToHttpStatusCodeMapper> _codeMapper;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly ResponderMiddleware _middleware;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private OcelotRequestDelegate _next;
|
||||
|
||||
public ResponderMiddlewareTests()
|
||||
{
|
||||
_responder = new Mock<IHttpResponder>();
|
||||
_codeMapper = new Mock<IErrorsToHttpStatusCodeMapper>();
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ResponderMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new ResponderMiddleware(_next, _responder.Object, _loggerFactory.Object, _codeMapper.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_return_any_errors()
|
||||
{
|
||||
this.Given(x => x.GivenTheHttpResponseMessageIs(new DownstreamResponse(new HttpResponseMessage())))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenThereAreNoErrors())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_any_errors()
|
||||
{
|
||||
this.Given(x => x.GivenTheHttpResponseMessageIs(new DownstreamResponse(new HttpResponseMessage())))
|
||||
.And(x => x.GivenThereArePipelineErrors(new UnableToFindDownstreamRouteError("/path", "GET")))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenThereAreNoErrors())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheHttpResponseMessageIs(DownstreamResponse response)
|
||||
{
|
||||
_downstreamContext.DownstreamResponse = response;
|
||||
}
|
||||
|
||||
private void ThenThereAreNoErrors()
|
||||
{
|
||||
//todo a better assert?
|
||||
}
|
||||
|
||||
private void GivenThereArePipelineErrors(Error error)
|
||||
{
|
||||
_downstreamContext.Errors.Add(error);
|
||||
using Ocelot.Middleware;
|
||||
|
||||
namespace Ocelot.UnitTests.Responder
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.DownstreamRouteFinder.Finder;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Responder;
|
||||
using Ocelot.Responder.Middleware;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
|
||||
public class ResponderMiddlewareTests
|
||||
{
|
||||
private readonly Mock<IHttpResponder> _responder;
|
||||
private readonly Mock<IErrorsToHttpStatusCodeMapper> _codeMapper;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly ResponderMiddleware _middleware;
|
||||
private RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public ResponderMiddlewareTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_responder = new Mock<IHttpResponder>();
|
||||
_codeMapper = new Mock<IErrorsToHttpStatusCodeMapper>();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<ResponderMiddleware>()).Returns(_logger.Object);
|
||||
_next = context => Task.CompletedTask;
|
||||
_middleware = new ResponderMiddleware(_next, _responder.Object, _loggerFactory.Object, _codeMapper.Object);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_not_return_any_errors()
|
||||
{
|
||||
this.Given(x => x.GivenTheHttpResponseMessageIs(new DownstreamResponse(new HttpResponseMessage())))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenThereAreNoErrors())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_return_any_errors()
|
||||
{
|
||||
this.Given(x => x.GivenTheHttpResponseMessageIs(new DownstreamResponse(new HttpResponseMessage())))
|
||||
.And(x => x.GivenThereArePipelineErrors(new UnableToFindDownstreamRouteError("/path", "GET")))
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenThereAreNoErrors())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void GivenTheHttpResponseMessageIs(DownstreamResponse response)
|
||||
{
|
||||
_httpContext.Items.UpsertDownstreamResponse(response);
|
||||
}
|
||||
|
||||
private void ThenThereAreNoErrors()
|
||||
{
|
||||
//todo a better assert?
|
||||
}
|
||||
|
||||
private void GivenThereArePipelineErrors(Error error)
|
||||
{
|
||||
_httpContext.Items.SetError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,36 +1,37 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Security.IPSecurity;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Security
|
||||
namespace Ocelot.UnitTests.Security
|
||||
{
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Ocelot.Configuration;
|
||||
using Ocelot.Configuration.Builder;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Security.IPSecurity;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
public class IPSecurityPolicyTests
|
||||
{
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private readonly DownstreamReRouteBuilder _downstreamReRouteBuilder;
|
||||
private readonly IPSecurityPolicy _ipSecurityPolicy;
|
||||
private Response response;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public IPSecurityPolicyTests()
|
||||
{
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com"));
|
||||
_downstreamContext.HttpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com")));
|
||||
_httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
|
||||
_downstreamReRouteBuilder = new DownstreamReRouteBuilder();
|
||||
_ipSecurityPolicy = new IPSecurityPolicy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
private void should_No_blocked_Ip_and_allowed_Ip()
|
||||
public void should_No_blocked_Ip_and_allowed_Ip()
|
||||
{
|
||||
this.Given(x => x.GivenSetDownstreamReRoute())
|
||||
.When(x => x.WhenTheSecurityPolicy())
|
||||
@ -39,9 +40,9 @@ namespace Ocelot.UnitTests.Security
|
||||
}
|
||||
|
||||
[Fact]
|
||||
private void should_blockedIp_clientIp_block()
|
||||
public void should_blockedIp_clientIp_block()
|
||||
{
|
||||
_downstreamContext.HttpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
|
||||
_httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
|
||||
this.Given(x => x.GivenSetBlockedIP())
|
||||
.Given(x => x.GivenSetDownstreamReRoute())
|
||||
.When(x => x.WhenTheSecurityPolicy())
|
||||
@ -50,9 +51,9 @@ namespace Ocelot.UnitTests.Security
|
||||
}
|
||||
|
||||
[Fact]
|
||||
private void should_blockedIp_clientIp_Not_block()
|
||||
public void should_blockedIp_clientIp_Not_block()
|
||||
{
|
||||
_downstreamContext.HttpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.2")[0];
|
||||
_httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.2")[0];
|
||||
this.Given(x => x.GivenSetBlockedIP())
|
||||
.Given(x => x.GivenSetDownstreamReRoute())
|
||||
.When(x => x.WhenTheSecurityPolicy())
|
||||
@ -61,9 +62,9 @@ namespace Ocelot.UnitTests.Security
|
||||
}
|
||||
|
||||
[Fact]
|
||||
private void should_allowedIp_clientIp_block()
|
||||
public void should_allowedIp_clientIp_block()
|
||||
{
|
||||
_downstreamContext.HttpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
|
||||
_httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.1")[0];
|
||||
this.Given(x => x.GivenSetAllowedIP())
|
||||
.Given(x => x.GivenSetDownstreamReRoute())
|
||||
.When(x => x.WhenTheSecurityPolicy())
|
||||
@ -72,9 +73,9 @@ namespace Ocelot.UnitTests.Security
|
||||
}
|
||||
|
||||
[Fact]
|
||||
private void should_allowedIp_clientIp_Not_block()
|
||||
public void should_allowedIp_clientIp_Not_block()
|
||||
{
|
||||
_downstreamContext.HttpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.2")[0];
|
||||
_httpContext.Connection.RemoteIpAddress = Dns.GetHostAddresses("192.168.1.2")[0];
|
||||
this.Given(x => x.GivenSetAllowedIP())
|
||||
.Given(x => x.GivenSetDownstreamReRoute())
|
||||
.When(x => x.WhenTheSecurityPolicy())
|
||||
@ -94,12 +95,12 @@ namespace Ocelot.UnitTests.Security
|
||||
|
||||
private void GivenSetDownstreamReRoute()
|
||||
{
|
||||
_downstreamContext.DownstreamReRoute = _downstreamReRouteBuilder.Build();
|
||||
_httpContext.Items.UpsertDownstreamReRoute(_downstreamReRouteBuilder.Build());
|
||||
}
|
||||
|
||||
private void WhenTheSecurityPolicy()
|
||||
{
|
||||
response = this._ipSecurityPolicy.Security(_downstreamContext).GetAwaiter().GetResult();
|
||||
response = _ipSecurityPolicy.Security(_httpContext.Items.DownstreamReRoute(), _httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThenSecurityPassing()
|
||||
|
@ -1,106 +1,110 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Security;
|
||||
using Ocelot.Security.Middleware;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Security
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Moq;
|
||||
using Ocelot.Errors;
|
||||
using Ocelot.Logging;
|
||||
using Ocelot.Middleware;
|
||||
using Ocelot.Request.Middleware;
|
||||
using Ocelot.Responses;
|
||||
using Ocelot.Security;
|
||||
using Ocelot.Security.Middleware;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using TestStack.BDDfy;
|
||||
using Xunit;
|
||||
|
||||
namespace Ocelot.UnitTests.Security
|
||||
{
|
||||
public class SecurityMiddlewareTests
|
||||
{
|
||||
private List<Mock<ISecurityPolicy>> _securityPolicyList;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly SecurityMiddleware _middleware;
|
||||
private readonly DownstreamContext _downstreamContext;
|
||||
private readonly OcelotRequestDelegate _next;
|
||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
||||
using Ocelot.Infrastructure.RequestData;
|
||||
using Shouldly;
|
||||
|
||||
public SecurityMiddlewareTests()
|
||||
public class SecurityMiddlewareTests
|
||||
{
|
||||
private List<Mock<ISecurityPolicy>> _securityPolicyList;
|
||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||
private Mock<IOcelotLogger> _logger;
|
||||
private readonly SecurityMiddleware _middleware;
|
||||
private readonly RequestDelegate _next;
|
||||
private HttpContext _httpContext;
|
||||
|
||||
public SecurityMiddlewareTests()
|
||||
{
|
||||
_httpContext = new DefaultHttpContext();
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<SecurityMiddleware>()).Returns(_logger.Object);
|
||||
_securityPolicyList = new List<Mock<ISecurityPolicy>>();
|
||||
_securityPolicyList.Add(new Mock<ISecurityPolicy>());
|
||||
_securityPolicyList.Add(new Mock<ISecurityPolicy>());
|
||||
_next = context =>
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
_middleware = new SecurityMiddleware(_next, _loggerFactory.Object, _securityPolicyList.Select(f => f.Object).ToList());
|
||||
_httpContext.Items.UpsertDownstreamRequest(new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_legal_request()
|
||||
{
|
||||
this.Given(x => x.GivenPassingSecurityVerification())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheRequestIsPassingSecurity())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_verification_failed_request()
|
||||
{
|
||||
this.Given(x => x.GivenNotPassingSecurityVerification())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheRequestIsNotPassingSecurity())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenPassingSecurityVerification()
|
||||
{
|
||||
foreach (var item in _securityPolicyList)
|
||||
{
|
||||
Response response = new OkResponse();
|
||||
item.Setup(x => x.Security(_httpContext.Items.DownstreamReRoute(), _httpContext)).Returns(Task.FromResult(response));
|
||||
}
|
||||
}
|
||||
|
||||
private void GivenNotPassingSecurityVerification()
|
||||
{
|
||||
for (int i = 0; i < _securityPolicyList.Count; i++)
|
||||
{
|
||||
Mock<ISecurityPolicy> item = _securityPolicyList[i];
|
||||
if (i == 0)
|
||||
{
|
||||
Error error = new UnauthenticatedError($"Not passing security verification");
|
||||
Response response = new ErrorResponse(error);
|
||||
item.Setup(x => x.Security(_httpContext.Items.DownstreamReRoute(), _httpContext)).Returns(Task.FromResult(response));
|
||||
}
|
||||
else
|
||||
{
|
||||
Response response = new OkResponse();
|
||||
item.Setup(x => x.Security(_httpContext.Items.DownstreamReRoute(), _httpContext)).Returns(Task.FromResult(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThenTheRequestIsPassingSecurity()
|
||||
{
|
||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||
_logger = new Mock<IOcelotLogger>();
|
||||
_loggerFactory.Setup(x => x.CreateLogger<SecurityMiddleware>()).Returns(_logger.Object);
|
||||
_securityPolicyList = new List<Mock<ISecurityPolicy>>();
|
||||
_securityPolicyList.Add(new Mock<ISecurityPolicy>());
|
||||
_securityPolicyList.Add(new Mock<ISecurityPolicy>());
|
||||
_next = context =>
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
_middleware = new SecurityMiddleware(_loggerFactory.Object, _securityPolicyList.Select(f => f.Object).ToList(), _next);
|
||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||
_downstreamContext.DownstreamRequest = new DownstreamRequest(new HttpRequestMessage(HttpMethod.Get, "http://test.com"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_legal_request()
|
||||
_httpContext.Items.Errors().Count.ShouldBe(0);
|
||||
}
|
||||
|
||||
private void ThenTheRequestIsNotPassingSecurity()
|
||||
{
|
||||
this.Given(x => x.GivenPassingSecurityVerification())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheRequestIsPassingSecurity())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void should_verification_failed_request()
|
||||
{
|
||||
this.Given(x => x.GivenNotPassingSecurityVerification())
|
||||
.When(x => x.WhenICallTheMiddleware())
|
||||
.Then(x => x.ThenTheRequestIsNotPassingSecurity())
|
||||
.BDDfy();
|
||||
}
|
||||
|
||||
private void GivenPassingSecurityVerification()
|
||||
{
|
||||
foreach (var item in _securityPolicyList)
|
||||
{
|
||||
Response response = new OkResponse();
|
||||
item.Setup(x => x.Security(_downstreamContext)).Returns(Task.FromResult(response));
|
||||
}
|
||||
}
|
||||
|
||||
private void GivenNotPassingSecurityVerification()
|
||||
{
|
||||
for (int i = 0; i < _securityPolicyList.Count; i++)
|
||||
{
|
||||
Mock<ISecurityPolicy> item = _securityPolicyList[i];
|
||||
if (i == 0)
|
||||
{
|
||||
Error error = new UnauthenticatedError($"Not passing security verification");
|
||||
Response response = new ErrorResponse(error);
|
||||
item.Setup(x => x.Security(_downstreamContext)).Returns(Task.FromResult(response));
|
||||
}
|
||||
else
|
||||
{
|
||||
Response response = new OkResponse();
|
||||
item.Setup(x => x.Security(_downstreamContext)).Returns(Task.FromResult(response));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WhenICallTheMiddleware()
|
||||
{
|
||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
private void ThenTheRequestIsPassingSecurity()
|
||||
{
|
||||
Assert.False(_downstreamContext.IsError);
|
||||
}
|
||||
|
||||
private void ThenTheRequestIsNotPassingSecurity()
|
||||
{
|
||||
Assert.True(_downstreamContext.IsError);
|
||||
}
|
||||
}
|
||||
}
|
||||
_httpContext.Items.Errors().Count.ShouldBeGreaterThan(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user