bunch of refactoring

This commit is contained in:
TomPallister 2016-10-26 21:38:44 +01:00
parent 9575adc90d
commit 367fa327b3
35 changed files with 264 additions and 157 deletions

View File

@ -13,6 +13,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
build.bat = build.bat
global.json = global.json
LICENSE.md = LICENSE.md
Ocelot.nuspec = Ocelot.nuspec
push-to-nuget.bat = push-to-nuget.bat
README.md = README.md
run-benchmarks.bat = run-benchmarks.bat
run-tests.bat = run-tests.bat

View File

@ -54,8 +54,8 @@ namespace Ocelot.DependencyInjection
services.AddSingleton<IAddHeadersToRequest, AddHeadersToRequest>();
services.AddSingleton<IClaimsParser, ClaimsParser>();
services.AddSingleton<IUrlPathToUrlTemplateMatcher, RegExUrlMatcher>();
services.AddSingleton<ITemplateVariableNameAndValueFinder, TemplateVariableNameAndValueFinder>();
services.AddSingleton<IDownstreamUrlTemplateVariableReplacer, DownstreamUrlTemplateVariableReplacer>();
services.AddSingleton<IUrlPathPlaceholderNameAndValueFinder, UrlPathPlaceholderNameAndValueFinder>();
services.AddSingleton<IDownstreamUrlPathPlaceholderReplacer, DownstreamUrlPathPlaceholderReplacer>();
services.AddSingleton<IDownstreamRouteFinder, DownstreamRouteFinder.Finder.DownstreamRouteFinder>();
services.AddSingleton<IHttpRequester, HttpClientHttpRequester>();
services.AddSingleton<IHttpResponder, HttpContextResponder>();

View File

@ -6,12 +6,12 @@ namespace Ocelot.DownstreamRouteFinder
{
public class DownstreamRoute
{
public DownstreamRoute(List<TemplateVariableNameAndValue> templateVariableNameAndValues, ReRoute reRoute)
public DownstreamRoute(List<UrlPathPlaceholderNameAndValue> templatePlaceholderNameAndValues, ReRoute reRoute)
{
TemplateVariableNameAndValues = templateVariableNameAndValues;
TemplatePlaceholderNameAndValues = templatePlaceholderNameAndValues;
ReRoute = reRoute;
}
public List<TemplateVariableNameAndValue> TemplateVariableNameAndValues { get; private set; }
public List<UrlPathPlaceholderNameAndValue> TemplatePlaceholderNameAndValues { get; private set; }
public ReRoute ReRoute { get; private set; }
}
}

View File

@ -12,29 +12,28 @@ namespace Ocelot.DownstreamRouteFinder.Finder
{
private readonly IOcelotConfigurationProvider _configProvider;
private readonly IUrlPathToUrlTemplateMatcher _urlMatcher;
private readonly ITemplateVariableNameAndValueFinder _templateVariableNameAndValueFinder;
private readonly IUrlPathPlaceholderNameAndValueFinder _urlPathPlaceholderNameAndValueFinder;
public DownstreamRouteFinder(IOcelotConfigurationProvider configProvider, IUrlPathToUrlTemplateMatcher urlMatcher, ITemplateVariableNameAndValueFinder templateVariableNameAndValueFinder)
public DownstreamRouteFinder(IOcelotConfigurationProvider configProvider, IUrlPathToUrlTemplateMatcher urlMatcher, IUrlPathPlaceholderNameAndValueFinder urlPathPlaceholderNameAndValueFinder)
{
_configProvider = configProvider;
_urlMatcher = urlMatcher;
_templateVariableNameAndValueFinder = templateVariableNameAndValueFinder;
_urlPathPlaceholderNameAndValueFinder = urlPathPlaceholderNameAndValueFinder;
}
public Response<DownstreamRoute> FindDownstreamRoute(string upstreamUrlPath, string upstreamHttpMethod)
{
var configuration = _configProvider.Get();
foreach (var template in configuration.Data.ReRoutes.Where(r => string.Equals(r.UpstreamHttpMethod, upstreamHttpMethod, StringComparison.CurrentCultureIgnoreCase)))
foreach (var reRoute in configuration.Data.ReRoutes.Where(r => string.Equals(r.UpstreamHttpMethod, upstreamHttpMethod, StringComparison.CurrentCultureIgnoreCase)))
{
var urlMatch = _urlMatcher.Match(upstreamUrlPath, template.UpstreamTemplatePattern);
var urlMatch = _urlMatcher.Match(upstreamUrlPath, reRoute.UpstreamTemplatePattern);
if (urlMatch.Data.Match)
{
var templateVariableNameAndValues = _templateVariableNameAndValueFinder.Find(upstreamUrlPath,
template.UpstreamTemplate);
var templateVariableNameAndValues = _urlPathPlaceholderNameAndValueFinder.Find(upstreamUrlPath, reRoute.UpstreamTemplate);
return new OkResponse<DownstreamRoute>(new DownstreamRoute(templateVariableNameAndValues.Data, template));
return new OkResponse<DownstreamRoute>(new DownstreamRoute(templateVariableNameAndValues.Data, reRoute));
}
}

View File

@ -1,10 +0,0 @@
using System.Collections.Generic;
using Ocelot.Responses;
namespace Ocelot.DownstreamRouteFinder.UrlMatcher
{
public interface ITemplateVariableNameAndValueFinder
{
Response<List<TemplateVariableNameAndValue>> Find(string upstreamUrlPath, string upstreamUrlPathTemplate);
}
}

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
using Ocelot.Responses;
namespace Ocelot.DownstreamRouteFinder.UrlMatcher
{
public interface IUrlPathPlaceholderNameAndValueFinder
{
Response<List<UrlPathPlaceholderNameAndValue>> Find(string upstreamUrlPath, string upstreamUrlPathTemplate);
}
}

View File

@ -1,8 +1,8 @@
namespace Ocelot.DownstreamRouteFinder.UrlMatcher
{
public class TemplateVariableNameAndValue
public class UrlPathPlaceholderNameAndValue
{
public TemplateVariableNameAndValue(string templateVariableName, string templateVariableValue)
public UrlPathPlaceholderNameAndValue(string templateVariableName, string templateVariableValue)
{
TemplateVariableName = templateVariableName;
TemplateVariableValue = templateVariableValue;

View File

@ -3,11 +3,11 @@ using Ocelot.Responses;
namespace Ocelot.DownstreamRouteFinder.UrlMatcher
{
public class TemplateVariableNameAndValueFinder : ITemplateVariableNameAndValueFinder
public class UrlPathPlaceholderNameAndValueFinder : IUrlPathPlaceholderNameAndValueFinder
{
public Response<List<TemplateVariableNameAndValue>> Find(string upstreamUrlPath, string upstreamUrlPathTemplate)
public Response<List<UrlPathPlaceholderNameAndValue>> Find(string upstreamUrlPath, string upstreamUrlPathTemplate)
{
var templateKeysAndValues = new List<TemplateVariableNameAndValue>();
var templateKeysAndValues = new List<UrlPathPlaceholderNameAndValue>();
int counterForUrl = 0;
@ -21,7 +21,7 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
var variableValue = GetPlaceholderVariableValue(upstreamUrlPath, counterForUrl);
var templateVariableNameAndValue = new TemplateVariableNameAndValue(variableName, variableValue);
var templateVariableNameAndValue = new UrlPathPlaceholderNameAndValue(variableName, variableValue);
templateKeysAndValues.Add(templateVariableNameAndValue);
@ -32,12 +32,12 @@ namespace Ocelot.DownstreamRouteFinder.UrlMatcher
continue;
}
return new OkResponse<List<TemplateVariableNameAndValue>>(templateKeysAndValues);
return new OkResponse<List<UrlPathPlaceholderNameAndValue>>(templateKeysAndValues);
}
counterForUrl++;
}
return new OkResponse<List<TemplateVariableNameAndValue>>(templateKeysAndValues);
return new OkResponse<List<UrlPathPlaceholderNameAndValue>>(templateKeysAndValues);
}
private string GetPlaceholderVariableValue(string urlPath, int counterForUrl)

View File

@ -10,11 +10,11 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
public class DownstreamUrlCreatorMiddleware : OcelotMiddleware
{
private readonly RequestDelegate _next;
private readonly IDownstreamUrlTemplateVariableReplacer _urlReplacer;
private readonly IDownstreamUrlPathPlaceholderReplacer _urlReplacer;
private readonly IRequestScopedDataRepository _requestScopedDataRepository;
public DownstreamUrlCreatorMiddleware(RequestDelegate next,
IDownstreamUrlTemplateVariableReplacer urlReplacer,
IDownstreamUrlPathPlaceholderReplacer urlReplacer,
IRequestScopedDataRepository requestScopedDataRepository)
:base(requestScopedDataRepository)
{
@ -33,7 +33,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
return;
}
var downstreamUrl = _urlReplacer.ReplaceTemplateVariables(downstreamRoute.Data);
var downstreamUrl = _urlReplacer.Replace(downstreamRoute.Data.ReRoute.DownstreamTemplate, downstreamRoute.Data.TemplatePlaceholderNameAndValues);
if (downstreamUrl.IsError)
{
@ -41,7 +41,7 @@ namespace Ocelot.DownstreamUrlCreator.Middleware
return;
}
_requestScopedDataRepository.Add("DownstreamUrl", downstreamUrl.Data);
_requestScopedDataRepository.Add("DownstreamUrl", downstreamUrl.Data.Value);
await _next.Invoke(context);
}

View File

@ -0,0 +1,12 @@
namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer
{
public class DownstreamUrl
{
public DownstreamUrl(string value)
{
Value = value;
}
public string Value { get; private set; }
}
}

View File

@ -1,23 +1,25 @@
using System.Collections.Generic;
using System.Text;
using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Responses;
namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer
{
public class DownstreamUrlTemplateVariableReplacer : IDownstreamUrlTemplateVariableReplacer
public class DownstreamUrlPathPlaceholderReplacer : IDownstreamUrlPathPlaceholderReplacer
{
public Response<string> ReplaceTemplateVariables(DownstreamRoute downstreamRoute)
public Response<DownstreamUrl> Replace(string downstreamTemplate, List<UrlPathPlaceholderNameAndValue> urlPathPlaceholderNameAndValues)
{
var upstreamUrl = new StringBuilder();
upstreamUrl.Append(downstreamRoute.ReRoute.DownstreamTemplate);
upstreamUrl.Append(downstreamTemplate);
foreach (var templateVarAndValue in downstreamRoute.TemplateVariableNameAndValues)
foreach (var placeholderVariableAndValue in urlPathPlaceholderNameAndValues)
{
upstreamUrl.Replace(templateVarAndValue.TemplateVariableName, templateVarAndValue.TemplateVariableValue);
upstreamUrl.Replace(placeholderVariableAndValue.TemplateVariableName, placeholderVariableAndValue.TemplateVariableValue);
}
return new OkResponse<string>(upstreamUrl.ToString());
return new OkResponse<DownstreamUrl>(new DownstreamUrl(upstreamUrl.ToString()));
}
}
}

View File

@ -1,10 +1,11 @@
using Ocelot.DownstreamRouteFinder;
using System.Collections.Generic;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Responses;
namespace Ocelot.DownstreamUrlCreator.UrlTemplateReplacer
{
public interface IDownstreamUrlTemplateVariableReplacer
public interface IDownstreamUrlPathPlaceholderReplacer
{
Response<string> ReplaceTemplateVariables(DownstreamRoute downstreamRoute);
Response<DownstreamUrl> Replace(string downstreamTemplate, List<UrlPathPlaceholderNameAndValue> urlPathPlaceholderNameAndValues);
}
}

View File

@ -0,0 +1,34 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace Ocelot.Middleware
{
public class ExceptionHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public ExceptionHandlerMiddleware(RequestDelegate next, ILoggerFactory loggerFactory)
{
_next = next;
_logger = loggerFactory.CreateLogger<ExceptionHandlerMiddleware>();
}
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch (Exception e)
{
_logger.LogError(new EventId(1, "global error"), "Exception caught in global error handler", e);
context.Response.StatusCode = 500;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync("Internal Server Error");
}
}
}
}

View File

@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Builder;
namespace Ocelot.Middleware
{
public static class ExceptionHandlerMiddlewareExtensions
{
public static IApplicationBuilder UseExceptionHandlerMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<ExceptionHandlerMiddleware>();
}
}
}

View File

@ -19,22 +19,34 @@ namespace Ocelot.Middleware
{
public static IApplicationBuilder UseOcelot(this IApplicationBuilder builder)
{
builder.UseHttpResponderMiddleware();
// This is registered to catch any global exceptions that are not handled
builder.UseExceptionHandlerMiddleware();
// This is registered first so it can catch any errors and issue an appropriate response
builder.UseHttpErrorResponderMiddleware();
// Then we get the downstream route information
builder.UseDownstreamRouteFinderMiddleware();
// Now we know where the client is going to go we can authenticate them
builder.UseAuthenticationMiddleware();
// The next thing we do is look at any claims transforms in case this is important for authorisation
builder.UseClaimsBuilderMiddleware();
// Now we have authenticated and done any claims transformation we can authorise the request
builder.UseAuthorisationMiddleware();
// Now we can run any header transformation logic
builder.UseHttpRequestHeadersBuilderMiddleware();
// This takes the downstream route we retrieved earlier and replaces any placeholders with the variables that should be used
builder.UseDownstreamUrlCreatorMiddleware();
// Everything should now be ready to build or HttpRequest
builder.UseHttpRequestBuilderMiddleware();
//We fire off the request and set the response on the context in this middleware
builder.UseHttpRequesterMiddleware();
return builder;
@ -44,7 +56,7 @@ namespace Ocelot.Middleware
{
builder.UseIfNotNull(middlewareConfiguration.PreHttpResponderMiddleware);
builder.UseHttpResponderMiddleware();
builder.UseHttpErrorResponderMiddleware();
builder.UseIfNotNull(middlewareConfiguration.PostHttpResponderMiddleware);

View File

@ -22,18 +22,13 @@ namespace Ocelot.RequestBuilder.Builder
if (content != null)
{
using (var reader = new StreamReader(content))
{
var body = await reader.ReadToEndAsync();
httpRequestMessage.Content = new StringContent(body);
}
httpRequestMessage.Content = new StreamContent(content);
}
if (!string.IsNullOrEmpty(contentType))
{
var splitCt = contentType.Split(';');
var cT = splitCt[0];
httpRequestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue(cT);
httpRequestMessage.Content.Headers.Remove("Content-Type");
httpRequestMessage.Content.Headers.TryAddWithoutValidation("Content-Type", contentType);
}
//todo get rid of if
@ -50,7 +45,7 @@ namespace Ocelot.RequestBuilder.Builder
//todo get rid of if..
if (header.Key.ToLower() != "host")
{
httpRequestMessage.Headers.Add(header.Key, header.Value.ToArray());
httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
}
}
}

View File

@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Http;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Middleware;
using Ocelot.RequestBuilder;
using Ocelot.Responder;
namespace Ocelot.Requester.Middleware
{
@ -11,15 +12,18 @@ namespace Ocelot.Requester.Middleware
private readonly RequestDelegate _next;
private readonly IHttpRequester _requester;
private readonly IRequestScopedDataRepository _requestScopedDataRepository;
private readonly IHttpResponder _responder;
public HttpRequesterMiddleware(RequestDelegate next,
IHttpRequester requester,
IRequestScopedDataRepository requestScopedDataRepository)
IRequestScopedDataRepository requestScopedDataRepository,
IHttpResponder responder)
:base(requestScopedDataRepository)
{
_next = next;
_requester = requester;
_requestScopedDataRepository = requestScopedDataRepository;
_responder = responder;
}
public async Task Invoke(HttpContext context)
@ -40,7 +44,12 @@ namespace Ocelot.Requester.Middleware
return;
}
_requestScopedDataRepository.Add("Response", response.Data);
var setResponse = await _responder.SetResponseOnHttpContext(context, response.Data);
if (setResponse.IsError)
{
SetPipelineError(response.Errors);
}
}
}
}

View File

@ -1,6 +1,7 @@
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Ocelot.Responses;
namespace Ocelot.Responder
{
@ -10,7 +11,7 @@ namespace Ocelot.Responder
/// </summary>
public class HttpContextResponder : IHttpResponder
{
public async Task<HttpContext> CreateResponse(HttpContext context, HttpResponseMessage response)
public async Task<Response> SetResponseOnHttpContext(HttpContext context, HttpResponseMessage response)
{
context.Response.OnStarting(x =>
{
@ -19,17 +20,17 @@ namespace Ocelot.Responder
}, context);
await context.Response.WriteAsync(await response.Content.ReadAsStringAsync());
return context;
return new OkResponse();
}
public async Task<HttpContext> CreateErrorResponse(HttpContext context, int statusCode)
public async Task<Response> SetErrorResponseOnContext(HttpContext context, int statusCode)
{
context.Response.OnStarting(x =>
{
context.Response.StatusCode = statusCode;
return Task.CompletedTask;
}, context);
return context;
return new OkResponse();
}
}
}

View File

@ -1,12 +1,13 @@
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Ocelot.Responses;
namespace Ocelot.Responder
{
public interface IHttpResponder
{
Task<HttpContext> CreateResponse(HttpContext context, HttpResponseMessage response);
Task<HttpContext> CreateErrorResponse(HttpContext context, int statusCode);
Task<Response> SetResponseOnHttpContext(HttpContext context, HttpResponseMessage response);
Task<Response> SetErrorResponseOnContext(HttpContext context, int statusCode);
}
}

View File

@ -6,14 +6,14 @@ using Ocelot.Middleware;
namespace Ocelot.Responder.Middleware
{
public class HttpResponderMiddleware : OcelotMiddleware
public class HttpErrorResponderMiddleware : OcelotMiddleware
{
private readonly RequestDelegate _next;
private readonly IHttpResponder _responder;
private readonly IRequestScopedDataRepository _requestScopedDataRepository;
private readonly IErrorsToHttpStatusCodeMapper _codeMapper;
public HttpResponderMiddleware(RequestDelegate next,
public HttpErrorResponderMiddleware(RequestDelegate next,
IHttpResponder responder,
IRequestScopedDataRepository requestScopedDataRepository,
IErrorsToHttpStatusCodeMapper codeMapper)
@ -37,18 +37,12 @@ namespace Ocelot.Responder.Middleware
if (!statusCode.IsError)
{
await _responder.CreateErrorResponse(context, statusCode.Data);
await _responder.SetErrorResponseOnContext(context, statusCode.Data);
}
else
{
await _responder.CreateErrorResponse(context, 500);
}
}
else
{
var response = _requestScopedDataRepository.Get<HttpResponseMessage>("Response");
await _responder.CreateResponse(context, response.Data);
await _responder.SetErrorResponseOnContext(context, 500);
}
}
}
}

View File

@ -4,9 +4,9 @@ namespace Ocelot.Responder.Middleware
{
public static class HttpResponderMiddlewareExtensions
{
public static IApplicationBuilder UseHttpResponderMiddleware(this IApplicationBuilder builder)
public static IApplicationBuilder UseHttpErrorResponderMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<HttpResponderMiddleware>();
return builder.UseMiddleware<HttpErrorResponderMiddleware>();
}
}
}

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
@ -67,8 +68,7 @@ namespace Ocelot.AcceptanceTests
{
PreHttpRequesterMiddleware = async (ctx, next) =>
{
var service = ctx.RequestServices.GetService<IRequestScopedDataRepository>();
service.Add("Response", new HttpResponseMessage {Content = new StringContent("PreHttpRequesterMiddleware")});
await ctx.Response.WriteAsync("PreHttpRequesterMiddleware");
}
};
@ -104,9 +104,10 @@ namespace Ocelot.AcceptanceTests
.UseUrls(url)
.Configure(app =>
{
app.Run(async context =>
app.Run(context =>
{
context.Response.StatusCode = statusCode;
return Task.CompletedTask;
});
})
.Build();

View File

@ -24,3 +24,6 @@ ReRoutes:
- DownstreamTemplate: http://www.bbc.co.uk
UpstreamTemplate: /
UpstreamHttpMethod: Get
- DownstreamTemplate: http://localhost:51879/api/products/{productId}
UpstreamTemplate: /products/{productId}
UpstreamHttpMethod: Get

View File

@ -56,7 +56,7 @@ namespace Ocelot.UnitTests.Authentication
[Fact]
public void happy_path()
{
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().Build())))
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().Build())))
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenNoExceptionsAreThrown())
.BDDfy();

View File

@ -58,7 +58,7 @@ namespace Ocelot.UnitTests.Authorization
[Fact]
public void happy_path()
{
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithIsAuthorised(true).Build())))
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithIsAuthorised(true).Build())))
.And(x => x.GivenTheAuthServiceReturns(new OkResponse<bool>(true)))
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheAuthServiceIsCalledCorrectly())

View File

@ -59,7 +59,7 @@ namespace Ocelot.UnitTests.ClaimsBuilder
[Fact]
public void happy_path()
{
var downstreamRoute = new DownstreamRoute(new List<TemplateVariableNameAndValue>(),
var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamTemplate("any old string")
.WithClaimsToClaims(new List<ClaimToThing>

View File

@ -57,7 +57,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
[Fact]
public void happy_path()
{
this.Given(x => x.GivenTheDownStreamRouteFinderReturns(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build())))
this.Given(x => x.GivenTheDownStreamRouteFinderReturns(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build())))
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
.BDDfy();

View File

@ -18,7 +18,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
private readonly IDownstreamRouteFinder _downstreamRouteFinder;
private readonly Mock<IOcelotConfigurationProvider> _mockConfig;
private readonly Mock<IUrlPathToUrlTemplateMatcher> _mockMatcher;
private readonly Mock<ITemplateVariableNameAndValueFinder> _finder;
private readonly Mock<IUrlPathPlaceholderNameAndValueFinder> _finder;
private string _upstreamUrlPath;
private Response<DownstreamRoute> _result;
private List<ReRoute> _reRoutesConfig;
@ -29,7 +29,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
{
_mockConfig = new Mock<IOcelotConfigurationProvider>();
_mockMatcher = new Mock<IUrlPathToUrlTemplateMatcher>();
_finder = new Mock<ITemplateVariableNameAndValueFinder>();
_finder = new Mock<IUrlPathPlaceholderNameAndValueFinder>();
_downstreamRouteFinder = new Ocelot.DownstreamRouteFinder.Finder.DownstreamRouteFinder(_mockConfig.Object, _mockMatcher.Object, _finder.Object);
}
@ -40,7 +40,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(
x =>
x.GivenTheTemplateVariableAndNameFinderReturns(
new OkResponse<List<TemplateVariableNameAndValue>>(new List<TemplateVariableNameAndValue>())))
new OkResponse<List<UrlPathPlaceholderNameAndValue>>(new List<UrlPathPlaceholderNameAndValue>())))
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
@ -55,7 +55,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheUpstreamHttpMethodIs("Get"))
.When(x => x.WhenICallTheFinder())
.Then(
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<TemplateVariableNameAndValue>(),
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamTemplate("someDownstreamPath")
.Build()
@ -71,7 +71,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(
x =>
x.GivenTheTemplateVariableAndNameFinderReturns(
new OkResponse<List<TemplateVariableNameAndValue>>(new List<TemplateVariableNameAndValue>())))
new OkResponse<List<UrlPathPlaceholderNameAndValue>>(new List<UrlPathPlaceholderNameAndValue>())))
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
@ -92,7 +92,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheUpstreamHttpMethodIs("Post"))
.When(x => x.WhenICallTheFinder())
.Then(
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<TemplateVariableNameAndValue>(),
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamTemplate("someDownstreamPathForAPost")
.Build()
@ -123,7 +123,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.BDDfy();
}
private void GivenTheTemplateVariableAndNameFinderReturns(Response<List<TemplateVariableNameAndValue>> response)
private void GivenTheTemplateVariableAndNameFinderReturns(Response<List<UrlPathPlaceholderNameAndValue>> response)
{
_finder
.Setup(x => x.Find(It.IsAny<string>(), It.IsAny<string>()))
@ -176,13 +176,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
{
_result.Data.ReRoute.DownstreamTemplate.ShouldBe(expected.ReRoute.DownstreamTemplate);
for (int i = 0; i < _result.Data.TemplateVariableNameAndValues.Count; i++)
for (int i = 0; i < _result.Data.TemplatePlaceholderNameAndValues.Count; i++)
{
_result.Data.TemplateVariableNameAndValues[i].TemplateVariableName.ShouldBe(
expected.TemplateVariableNameAndValues[i].TemplateVariableName);
_result.Data.TemplatePlaceholderNameAndValues[i].TemplateVariableName.ShouldBe(
expected.TemplatePlaceholderNameAndValues[i].TemplateVariableName);
_result.Data.TemplateVariableNameAndValues[i].TemplateVariableValue.ShouldBe(
expected.TemplateVariableNameAndValues[i].TemplateVariableValue);
_result.Data.TemplatePlaceholderNameAndValues[i].TemplateVariableValue.ShouldBe(
expected.TemplatePlaceholderNameAndValues[i].TemplateVariableValue);
}
_result.IsError.ShouldBeFalse();

View File

@ -10,14 +10,14 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
{
public class UrlPathToUrlTemplateMatcherTests
{
private readonly ITemplateVariableNameAndValueFinder _finder;
private readonly IUrlPathPlaceholderNameAndValueFinder _finder;
private string _downstreamUrlPath;
private string _downstreamPathTemplate;
private Response<List<TemplateVariableNameAndValue>> _result;
private Response<List<UrlPathPlaceholderNameAndValue>> _result;
public UrlPathToUrlTemplateMatcherTests()
{
_finder = new TemplateVariableNameAndValueFinder();
_finder = new UrlPathPlaceholderNameAndValueFinder();
}
[Fact]
@ -26,7 +26,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
this.Given(x => x.GivenIHaveAUpstreamPath(""))
.And(x => x.GivenIHaveAnUpstreamUrlTemplate(""))
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
.And(x => x.ThenTheTemplatesVariablesAre(new List<UrlPathPlaceholderNameAndValue>()))
.BDDfy();
}
@ -36,7 +36,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
this.Given(x => x.GivenIHaveAUpstreamPath("api"))
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api"))
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
.And(x => x.ThenTheTemplatesVariablesAre(new List<UrlPathPlaceholderNameAndValue>()))
.BDDfy();
}
@ -46,7 +46,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
this.Given(x => x.GivenIHaveAUpstreamPath("api/"))
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/"))
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
.And(x => x.ThenTheTemplatesVariablesAre(new List<UrlPathPlaceholderNameAndValue>()))
.BDDfy();
}
@ -56,16 +56,16 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/"))
.Given(x => x.GivenIHaveAnUpstreamUrlTemplate("api/product/products/"))
.When(x => x.WhenIFindTheUrlVariableNamesAndValues())
.And(x => x.ThenTheTemplatesVariablesAre(new List<TemplateVariableNameAndValue>()))
.And(x => x.ThenTheTemplatesVariablesAre(new List<UrlPathPlaceholderNameAndValue>()))
.BDDfy();
}
[Fact]
public void can_match_down_stream_url_with_downstream_template_with_one_place_holder()
{
var expectedTemplates = new List<TemplateVariableNameAndValue>
var expectedTemplates = new List<UrlPathPlaceholderNameAndValue>
{
new TemplateVariableNameAndValue("{productId}", "1")
new UrlPathPlaceholderNameAndValue("{productId}", "1")
};
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1"))
@ -78,10 +78,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
[Fact]
public void can_match_down_stream_url_with_downstream_template_with_two_place_holders()
{
var expectedTemplates = new List<TemplateVariableNameAndValue>
var expectedTemplates = new List<UrlPathPlaceholderNameAndValue>
{
new TemplateVariableNameAndValue("{productId}", "1"),
new TemplateVariableNameAndValue("{categoryId}", "2")
new UrlPathPlaceholderNameAndValue("{productId}", "1"),
new UrlPathPlaceholderNameAndValue("{categoryId}", "2")
};
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/2"))
@ -94,10 +94,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
[Fact]
public void can_match_down_stream_url_with_downstream_template_with_two_place_holders_seperated_by_something()
{
var expectedTemplates = new List<TemplateVariableNameAndValue>
var expectedTemplates = new List<UrlPathPlaceholderNameAndValue>
{
new TemplateVariableNameAndValue("{productId}", "1"),
new TemplateVariableNameAndValue("{categoryId}", "2")
new UrlPathPlaceholderNameAndValue("{productId}", "1"),
new UrlPathPlaceholderNameAndValue("{categoryId}", "2")
};
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2"))
@ -110,11 +110,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
[Fact]
public void can_match_down_stream_url_with_downstream_template_with_three_place_holders_seperated_by_something()
{
var expectedTemplates = new List<TemplateVariableNameAndValue>
var expectedTemplates = new List<UrlPathPlaceholderNameAndValue>
{
new TemplateVariableNameAndValue("{productId}", "1"),
new TemplateVariableNameAndValue("{categoryId}", "2"),
new TemplateVariableNameAndValue("{variantId}", "123")
new UrlPathPlaceholderNameAndValue("{productId}", "1"),
new UrlPathPlaceholderNameAndValue("{categoryId}", "2"),
new UrlPathPlaceholderNameAndValue("{variantId}", "123")
};
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/123"))
@ -127,10 +127,10 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
[Fact]
public void can_match_down_stream_url_with_downstream_template_with_three_place_holders()
{
var expectedTemplates = new List<TemplateVariableNameAndValue>
var expectedTemplates = new List<UrlPathPlaceholderNameAndValue>
{
new TemplateVariableNameAndValue("{productId}", "1"),
new TemplateVariableNameAndValue("{categoryId}", "2")
new UrlPathPlaceholderNameAndValue("{productId}", "1"),
new UrlPathPlaceholderNameAndValue("{categoryId}", "2")
};
this.Given(x => x.GivenIHaveAUpstreamPath("api/product/products/1/categories/2/variant/"))
@ -140,7 +140,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher
.BDDfy();
}
private void ThenTheTemplatesVariablesAre(List<TemplateVariableNameAndValue> expectedResults)
private void ThenTheTemplatesVariablesAre(List<UrlPathPlaceholderNameAndValue> expectedResults)
{
foreach (var expectedResult in expectedResults)
{

View File

@ -20,19 +20,19 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
{
public class DownstreamUrlCreatorMiddlewareTests : IDisposable
{
private readonly Mock<IDownstreamUrlTemplateVariableReplacer> _downstreamUrlTemplateVariableReplacer;
private readonly Mock<IDownstreamUrlPathPlaceholderReplacer> _downstreamUrlTemplateVariableReplacer;
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
private readonly string _url;
private readonly TestServer _server;
private readonly HttpClient _client;
private Response<DownstreamRoute> _downstreamRoute;
private HttpResponseMessage _result;
private OkResponse<string> _downstreamUrl;
private OkResponse<DownstreamUrl> _downstreamUrl;
public DownstreamUrlCreatorMiddlewareTests()
{
_url = "http://localhost:51879";
_downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamUrlTemplateVariableReplacer>();
_downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamUrlPathPlaceholderReplacer>();
_scopedRepository = new Mock<IRequestScopedDataRepository>();
var builder = new WebHostBuilder()
@ -58,7 +58,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
[Fact]
public void happy_path()
{
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build())))
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("any old string").Build())))
.And(x => x.TheUrlReplacerReturns("any old string"))
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
@ -67,16 +67,16 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
private void TheUrlReplacerReturns(string downstreamUrl)
{
_downstreamUrl = new OkResponse<string>(downstreamUrl);
_downstreamUrl = new OkResponse<DownstreamUrl>(new DownstreamUrl(downstreamUrl));
_downstreamUrlTemplateVariableReplacer
.Setup(x => x.ReplaceTemplateVariables(It.IsAny<DownstreamRoute>()))
.Setup(x => x.Replace(It.IsAny<string>(), It.IsAny<List<UrlPathPlaceholderNameAndValue>>()))
.Returns(_downstreamUrl);
}
private void ThenTheScopedDataRepositoryIsCalledCorrectly()
{
_scopedRepository
.Verify(x => x.Add("DownstreamUrl", _downstreamUrl.Data), Times.Once());
.Verify(x => x.Add("DownstreamUrl", _downstreamUrl.Data.Value), Times.Once());
}
private void WhenICallTheMiddleware()

View File

@ -13,18 +13,18 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
public class UpstreamUrlPathTemplateVariableReplacerTests
{
private DownstreamRoute _downstreamRoute;
private Response<string> _result;
private readonly IDownstreamUrlTemplateVariableReplacer _downstreamUrlPathReplacer;
private Response<DownstreamUrl> _result;
private readonly IDownstreamUrlPathPlaceholderReplacer _downstreamUrlPathReplacer;
public UpstreamUrlPathTemplateVariableReplacerTests()
{
_downstreamUrlPathReplacer = new DownstreamUrlTemplateVariableReplacer();
_downstreamUrlPathReplacer = new DownstreamUrlPathPlaceholderReplacer();
}
[Fact]
public void can_replace_no_template_variables()
{
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().Build())))
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned(""))
.BDDfy();
@ -33,7 +33,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
[Fact]
public void can_replace_no_template_variables_with_slash()
{
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("/").Build())))
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("/").Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("/"))
.BDDfy();
@ -42,7 +42,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
[Fact]
public void can_replace_url_no_slash()
{
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("api").Build())))
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("api").Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("api"))
.BDDfy();
@ -51,7 +51,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
[Fact]
public void can_replace_url_one_slash()
{
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("api/").Build())))
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("api/").Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("api/"))
.BDDfy();
@ -60,7 +60,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
[Fact]
public void can_replace_url_multiple_slash()
{
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<TemplateVariableNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("api/product/products/").Build())))
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(), new ReRouteBuilder().WithDownstreamTemplate("api/product/products/").Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("api/product/products/"))
.BDDfy();
@ -69,9 +69,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
[Fact]
public void can_replace_url_one_template_variable()
{
var templateVariables = new List<TemplateVariableNameAndValue>()
var templateVariables = new List<UrlPathPlaceholderNameAndValue>()
{
new TemplateVariableNameAndValue("{productId}", "1")
new UrlPathPlaceholderNameAndValue("{productId}", "1")
};
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamTemplate("productservice/products/{productId}/").Build())))
@ -83,9 +83,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
[Fact]
public void can_replace_url_one_template_variable_with_path_after()
{
var templateVariables = new List<TemplateVariableNameAndValue>()
var templateVariables = new List<UrlPathPlaceholderNameAndValue>()
{
new TemplateVariableNameAndValue("{productId}", "1")
new UrlPathPlaceholderNameAndValue("{productId}", "1")
};
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamTemplate("productservice/products/{productId}/variants").Build())))
@ -97,10 +97,10 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
[Fact]
public void can_replace_url_two_template_variable()
{
var templateVariables = new List<TemplateVariableNameAndValue>()
var templateVariables = new List<UrlPathPlaceholderNameAndValue>()
{
new TemplateVariableNameAndValue("{productId}", "1"),
new TemplateVariableNameAndValue("{variantId}", "12")
new UrlPathPlaceholderNameAndValue("{productId}", "1"),
new UrlPathPlaceholderNameAndValue("{variantId}", "12")
};
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamTemplate("productservice/products/{productId}/variants/{variantId}").Build())))
@ -112,11 +112,11 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
[Fact]
public void can_replace_url_three_template_variable()
{
var templateVariables = new List<TemplateVariableNameAndValue>()
var templateVariables = new List<UrlPathPlaceholderNameAndValue>()
{
new TemplateVariableNameAndValue("{productId}", "1"),
new TemplateVariableNameAndValue("{variantId}", "12"),
new TemplateVariableNameAndValue("{categoryId}", "34")
new UrlPathPlaceholderNameAndValue("{productId}", "1"),
new UrlPathPlaceholderNameAndValue("{variantId}", "12"),
new UrlPathPlaceholderNameAndValue("{categoryId}", "34")
};
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables, new ReRouteBuilder().WithDownstreamTemplate("productservice/category/{categoryId}/products/{productId}/variants/{variantId}").Build())))
@ -132,12 +132,12 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
private void WhenIReplaceTheTemplateVariables()
{
_result = _downstreamUrlPathReplacer.ReplaceTemplateVariables(_downstreamRoute);
_result = _downstreamUrlPathReplacer.Replace(_downstreamRoute.ReRoute.DownstreamTemplate, _downstreamRoute.TemplatePlaceholderNameAndValues);
}
private void ThenTheDownstreamUrlPathIsReturned(string expected)
{
_result.Data.ShouldBe(expected);
_result.Data.Value.ShouldBe(expected);
}
}
}

View File

@ -58,7 +58,7 @@ namespace Ocelot.UnitTests.HeaderBuilder
[Fact]
public void happy_path()
{
var downstreamRoute = new DownstreamRoute(new List<TemplateVariableNameAndValue>(),
var downstreamRoute = new DownstreamRoute(new List<UrlPathPlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamTemplate("any old string")
.WithClaimsToHeaders(new List<ClaimToThing>

View File

@ -81,6 +81,23 @@ namespace Ocelot.UnitTests.RequestBuilder
.BDDfy();
}
[Fact]
public void should_use_unvalidated_http_content_headers()
{
this.Given(x => x.GivenIHaveHttpMethod("POST"))
.And(x => x.GivenIHaveDownstreamUrl("http://www.bbc.co.uk"))
.And(x => x.GivenIHaveTheHttpContent(new StringContent("Hi from Tom")))
.And(x => x.GivenTheContentTypeIs("application/json; charset=utf-8"))
.When(x => x.WhenICreateARequest())
.And(x => x.ThenTheCorrectContentHeadersAreUsed(new HeaderDictionary
{
{
"Content-Type", "application/json; charset=utf-8"
}
}))
.BDDfy();
}
[Fact]
public void should_use_headers()
{

View File

@ -3,6 +3,7 @@ using System.IO;
using System.Net;
using System.Net.Http;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Moq;
@ -10,6 +11,7 @@ using Ocelot.Infrastructure.RequestData;
using Ocelot.RequestBuilder;
using Ocelot.Requester;
using Ocelot.Requester.Middleware;
using Ocelot.Responder;
using Ocelot.Responses;
using TestStack.BDDfy;
using Xunit;
@ -26,16 +28,19 @@ namespace Ocelot.UnitTests.Requester
private HttpResponseMessage _result;
private OkResponse<HttpResponseMessage> _response;
private OkResponse<Request> _request;
private readonly Mock<IHttpResponder> _responder;
public HttpRequesterMiddlewareTests()
{
_url = "http://localhost:51879";
_requester = new Mock<IHttpRequester>();
_scopedRepository = new Mock<IRequestScopedDataRepository>();
_responder = new Mock<IHttpResponder>();
var builder = new WebHostBuilder()
.ConfigureServices(x =>
{
x.AddSingleton(_responder.Object);
x.AddSingleton(_requester.Object);
x.AddSingleton(_scopedRepository.Object);
})
@ -58,8 +63,9 @@ namespace Ocelot.UnitTests.Requester
{
this.Given(x => x.GivenTheRequestIs(new Request(new HttpRequestMessage(),new CookieContainer())))
.And(x => x.GivenTheRequesterReturns(new HttpResponseMessage()))
.And(x => x.GivenTheResponderReturns())
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
.Then(x => x.ThenTheResponderIsCalledCorrectly())
.BDDfy();
}
@ -71,10 +77,17 @@ namespace Ocelot.UnitTests.Requester
.ReturnsAsync(_response);
}
private void ThenTheScopedDataRepositoryIsCalledCorrectly()
private void GivenTheResponderReturns()
{
_scopedRepository
.Verify(x => x.Add("Response", _response.Data), Times.Once());
_responder
.Setup(x => x.SetResponseOnHttpContext(It.IsAny<HttpContext>(), _response.Data))
.ReturnsAsync(new OkResponse());
}
private void ThenTheResponderIsCalledCorrectly()
{
_responder
.Verify(x => x.SetResponseOnHttpContext(It.IsAny<HttpContext>(), _response.Data), Times.Once());
}
private void WhenICallTheMiddleware()

View File

@ -15,7 +15,7 @@ using Xunit;
namespace Ocelot.UnitTests.Responder
{
public class HttpResponderMiddlewareTests : IDisposable
public class HttpErrorResponderMiddlewareTests : IDisposable
{
private readonly Mock<IHttpResponder> _responder;
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
@ -26,7 +26,7 @@ namespace Ocelot.UnitTests.Responder
private HttpResponseMessage _result;
private OkResponse<HttpResponseMessage> _response;
public HttpResponderMiddlewareTests()
public HttpErrorResponderMiddlewareTests()
{
_url = "http://localhost:51879";
_responder = new Mock<IHttpResponder>();
@ -47,7 +47,7 @@ namespace Ocelot.UnitTests.Responder
.UseUrls(_url)
.Configure(app =>
{
app.UseHttpResponderMiddleware();
app.UseHttpErrorResponderMiddleware();
});
_server = new TestServer(builder);
@ -60,7 +60,7 @@ namespace Ocelot.UnitTests.Responder
this.Given(x => x.GivenTheHttpResponseMessageIs(new HttpResponseMessage()))
.And(x => x.GivenThereAreNoPipelineErrors())
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.TheResponderIsCalledCorrectly())
.Then(x => x.ThenThereAreNoErrors())
.BDDfy();
}
@ -71,10 +71,9 @@ namespace Ocelot.UnitTests.Responder
.Returns(new OkResponse<bool>(false));
}
private void TheResponderIsCalledCorrectly()
private void ThenThereAreNoErrors()
{
_responder
.Verify(x => x.CreateResponse(It.IsAny<HttpContext>(), _response.Data), Times.Once);
//todo a better assert?
}
private void WhenICallTheMiddleware()