Feature/downstream aggregation (#248)

* started messing around with this on the train last night

* mega hacking away to change middleware into Ocelot iddleware

* scoped data repo back in

* broken commit getting tests working

* another broken commit farting around with tests

* all unit tests passing again

* mw pipeline for ocelot...still loads of hacks but getting there now to get acceptance tests working, then fix config so you can have aggregate and then imlement multiplexer, then mapping to response...loads to do

* all tests passing before aggregation feature implemented

* removed all the request middleware stuff we dont need it

* updated how errors work...tho i think there could be edge case here when aggregating because one downstream could error and this would effect another

* removed multiplexer so you dont have to send route down, this isnt very thread safe...sigh

* hacking around getting the config for aggregates in, this might change

* refactored builder and unit tests passing now

* Updated a bunch of ports for tests

* plugged in code to create reroutes that are aggregates

* made multiplexer a class

* hacked test to death

* simple aggregator done, initial validation done

* removed request id from context, it is still specific for http request

* now aggregates to json always

* docs for aggregate reroutes

* Updated docs
This commit is contained in:
Tom Pallister
2018-02-27 08:22:47 +00:00
committed by GitHub
parent 2573657ec2
commit d1926268ac
137 changed files with 4032 additions and 2007 deletions

View File

@ -0,0 +1,372 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Ocelot.Configuration.File;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
namespace Ocelot.AcceptanceTests
{
public class AggregateTests : IDisposable
{
private IWebHost _serviceOneBuilder;
private IWebHost _serviceTwoBuilder;
private readonly Steps _steps;
private string _downstreamPathOne;
private string _downstreamPathTwo;
public AggregateTests()
{
_steps = new Steps();
}
[Fact]
public void should_return_response_200_with_simple_url()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51885,
}
},
UpstreamPathTemplate = "/laura",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Laura"
},
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51886,
}
},
UpstreamPathTemplate = "/tom",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Tom"
}
},
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
UpstreamPathTemplate = "/",
UpstreamHost = "localhost",
ReRouteKeys = new List<string>
{
"Tom",
"Laura"
}
}
}
};
var expected = "{\"Laura\":{Hello from Laura},\"Tom\":{Hello from Tom}}";
this.Given(x => x.GivenServiceOneIsRunning("http://localhost:51885", "/", 200, "{Hello from Laura}"))
.Given(x => x.GivenServiceTwoIsRunning("http://localhost:51886", "/", 200, "{Hello from Tom}"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe(expected))
.And(x => ThenTheDownstreamUrlPathShouldBe("/", "/"))
.BDDfy();
}
[Fact]
public void should_return_response_200_with_simple_url_one_service_404()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51881,
}
},
UpstreamPathTemplate = "/laura",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Laura"
},
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51882,
}
},
UpstreamPathTemplate = "/tom",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Tom"
}
},
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
UpstreamPathTemplate = "/",
UpstreamHost = "localhost",
ReRouteKeys = new List<string>
{
"Tom",
"Laura"
}
}
}
};
var expected = "{\"Laura\":,\"Tom\":{Hello from Tom}}";
this.Given(x => x.GivenServiceOneIsRunning("http://localhost:51881", "/", 404, ""))
.Given(x => x.GivenServiceTwoIsRunning("http://localhost:51882", "/", 200, "{Hello from Tom}"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe(expected))
.And(x => ThenTheDownstreamUrlPathShouldBe("/", "/"))
.BDDfy();
}
[Fact]
public void should_return_response_200_with_simple_url_both_service_404()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51883,
}
},
UpstreamPathTemplate = "/laura",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Laura"
},
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51884,
}
},
UpstreamPathTemplate = "/tom",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Tom"
}
},
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
UpstreamPathTemplate = "/",
UpstreamHost = "localhost",
ReRouteKeys = new List<string>
{
"Tom",
"Laura"
}
}
}
};
var expected = "{\"Laura\":,\"Tom\":}";
this.Given(x => x.GivenServiceOneIsRunning("http://localhost:51883", "/", 404, ""))
.Given(x => x.GivenServiceTwoIsRunning("http://localhost:51884", "/", 404, ""))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe(expected))
.And(x => ThenTheDownstreamUrlPathShouldBe("/", "/"))
.BDDfy();
}
[Fact]
public void should_be_thread_safe()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51878,
}
},
UpstreamPathTemplate = "/laura",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Laura"
},
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51880,
}
},
UpstreamPathTemplate = "/tom",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Tom"
}
},
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
UpstreamPathTemplate = "/",
UpstreamHost = "localhost",
ReRouteKeys = new List<string>
{
"Tom",
"Laura"
}
}
}
};
this.Given(x => x.GivenServiceOneIsRunning("http://localhost:51878", "/", 200, "{Hello from Laura}"))
.Given(x => x.GivenServiceTwoIsRunning("http://localhost:51880", "/", 200, "{Hello from Tom}"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIMakeLotsOfDifferentRequestsToTheApiGateway())
.And(x => ThenTheDownstreamUrlPathShouldBe("/", "/"))
.BDDfy();
}
private void GivenServiceOneIsRunning(string baseUrl, string basePath, int statusCode, string responseBody)
{
_serviceOneBuilder = new WebHostBuilder()
.UseUrls(baseUrl)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.Configure(app =>
{
app.UsePathBase(basePath);
app.Run(async context =>
{
_downstreamPathOne = !string.IsNullOrEmpty(context.Request.PathBase.Value) ? context.Request.PathBase.Value : context.Request.Path.Value;
if(_downstreamPathOne != basePath)
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync("downstream path didnt match base path");
}
else
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(responseBody);
}
});
})
.Build();
_serviceOneBuilder.Start();
}
private void GivenServiceTwoIsRunning(string baseUrl, string basePath, int statusCode, string responseBody)
{
_serviceOneBuilder = new WebHostBuilder()
.UseUrls(baseUrl)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.Configure(app =>
{
app.UsePathBase(basePath);
app.Run(async context =>
{
_downstreamPathTwo = !string.IsNullOrEmpty(context.Request.PathBase.Value) ? context.Request.PathBase.Value : context.Request.Path.Value;
if(_downstreamPathTwo != basePath)
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync("downstream path didnt match base path");
}
else
{
context.Response.StatusCode = statusCode;
await context.Response.WriteAsync(responseBody);
}
});
})
.Build();
_serviceOneBuilder.Start();
}
internal void ThenTheDownstreamUrlPathShouldBe(string expectedDownstreamPathOne, string expectedDownstreamPath)
{
_downstreamPathOne.ShouldBe(expectedDownstreamPathOne);
_downstreamPathTwo.ShouldBe(expectedDownstreamPath);
}
public void Dispose()
{
_serviceOneBuilder?.Dispose();
_serviceTwoBuilder?.Dispose();
_steps.Dispose();
}
}
}

View File

@ -37,7 +37,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51899,
}
},
DownstreamScheme = "http",
@ -51,13 +51,13 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", 200, "Hello from Laura"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.Given(x => x.GivenTheServiceNowReturns("http://localhost:51879", 200, "Hello from Tom"))
.Given(x => x.GivenTheServiceNowReturns("http://localhost:51899", 200, "Hello from Tom"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
@ -80,7 +80,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51899,
}
},
DownstreamScheme = "http",
@ -94,13 +94,13 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", 200, "Hello from Laura"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunningUsingJsonSerializedCache())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.Given(x => x.GivenTheServiceNowReturns("http://localhost:51879", 200, "Hello from Tom"))
.Given(x => x.GivenTheServiceNowReturns("http://localhost:51899", 200, "Hello from Tom"))
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
@ -122,7 +122,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51899,
}
},
DownstreamScheme = "http",
@ -136,13 +136,13 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", 200, "Hello from Laura"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51899", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
.Given(x => x.GivenTheServiceNowReturns("http://localhost:51879", 200, "Hello from Tom"))
.Given(x => x.GivenTheServiceNowReturns("http://localhost:51899", 200, "Hello from Tom"))
.And(x => x.GivenTheCacheExpires())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))

View File

@ -36,7 +36,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51877,
}
},
DownstreamScheme = "http",
@ -46,7 +46,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/products/1", 200, "Some Product"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51877", "/api/products/1", 200, "Some Product"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/PRODUCTS/1"))
@ -69,7 +69,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51877,
}
},
DownstreamScheme = "http",
@ -80,7 +80,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/products/1", 200, "Some Product"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51877", "/api/products/1", 200, "Some Product"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/PRODUCTS/1"))
@ -103,7 +103,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51877,
}
},
DownstreamScheme = "http",
@ -114,7 +114,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/products/1", 200, "Some Product"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51877", "/api/products/1", 200, "Some Product"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/PRODUCTS/1"))
@ -137,7 +137,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51877,
}
},
DownstreamScheme = "http",
@ -148,7 +148,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/products/1", 200, "Some Product"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51877", "/api/products/1", 200, "Some Product"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/PRODUCTS/1"))
@ -171,7 +171,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51877,
}
},
DownstreamScheme = "http",
@ -182,7 +182,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/products/1", 200, "Some Product"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51877", "/api/products/1", 200, "Some Product"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/PRODUCTS/1"))
@ -205,7 +205,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51877,
}
},
DownstreamScheme = "http",
@ -216,7 +216,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/products/1", 200, "Some Product"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51877", "/api/products/1", 200, "Some Product"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/PRODUCTS/1"))

View File

@ -48,7 +48,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51876,
}
},
DownstreamScheme = "http",
@ -81,7 +81,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/ClientRateLimit"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", "/api/ClientRateLimit"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit("/api/ClientRateLimit",1))
@ -109,7 +109,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51876,
}
},
DownstreamScheme = "http",
@ -140,7 +140,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/ClientRateLimit"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51876", "/api/ClientRateLimit"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit("/api/ClientRateLimit", 4))

View File

@ -32,7 +32,7 @@ namespace Ocelot.AcceptanceTests
[Fact]
public void should_call_pre_query_string_builder_middleware()
{
var configuration = new OcelotMiddlewareConfiguration
var configuration = new OcelotPipelineConfiguration
{
AuthorisationMiddleware = async (ctx, next) =>
{
@ -75,7 +75,7 @@ namespace Ocelot.AcceptanceTests
[Fact]
public void should_call_authorisation_middleware()
{
var configuration = new OcelotMiddlewareConfiguration
var configuration = new OcelotPipelineConfiguration
{
AuthorisationMiddleware = async (ctx, next) =>
{
@ -118,7 +118,7 @@ namespace Ocelot.AcceptanceTests
[Fact]
public void should_call_authentication_middleware()
{
var configuration = new OcelotMiddlewareConfiguration
var configuration = new OcelotPipelineConfiguration
{
AuthenticationMiddleware = async (ctx, next) =>
{
@ -161,7 +161,7 @@ namespace Ocelot.AcceptanceTests
[Fact]
public void should_call_pre_error_middleware()
{
var configuration = new OcelotMiddlewareConfiguration
var configuration = new OcelotPipelineConfiguration
{
PreErrorResponderMiddleware = async (ctx, next) =>
{
@ -204,7 +204,7 @@ namespace Ocelot.AcceptanceTests
[Fact]
public void should_call_pre_authorisation_middleware()
{
var configuration = new OcelotMiddlewareConfiguration
var configuration = new OcelotPipelineConfiguration
{
PreAuthorisationMiddleware = async (ctx, next) =>
{
@ -247,7 +247,7 @@ namespace Ocelot.AcceptanceTests
[Fact]
public void should_call_pre_http_authentication_middleware()
{
var configuration = new OcelotMiddlewareConfiguration
var configuration = new OcelotPipelineConfiguration
{
PreAuthenticationMiddleware = async (ctx, next) =>
{

View File

@ -41,7 +41,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51871,
}
},
UpstreamPathTemplate = "/",
@ -54,7 +54,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Laz"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51871", "/", 200, "Laz"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.And(x => _steps.GivenIAddAHeader("Laz", "D"))
@ -80,7 +80,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51871,
}
},
UpstreamPathTemplate = "/",
@ -93,7 +93,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Location", "http://www.bbc.co.uk/"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51871", "/", 200, "Location", "http://www.bbc.co.uk/"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))

View File

@ -41,7 +41,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51872,
}
},
UpstreamPathTemplate = "/",
@ -57,7 +57,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAPossiblyBrokenServiceRunningOn("http://localhost:51879", "Hello from Laura"))
this.Given(x => x.GivenThereIsAPossiblyBrokenServiceRunningOn("http://localhost:51872", "Hello from Laura"))
.Given(x => _steps.GivenThereIsAConfiguration(configuration))
.Given(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
@ -92,7 +92,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51872,
}
},
UpstreamPathTemplate = "/",
@ -122,7 +122,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAPossiblyBrokenServiceRunningOn("http://localhost:51879", "Hello from Laura"))
this.Given(x => x.GivenThereIsAPossiblyBrokenServiceRunningOn("http://localhost:51872", "Hello from Laura"))
.And(x => x.GivenThereIsAServiceRunningOn("http://localhost:51880/", 200, "Hello from Tom"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())

View File

@ -39,7 +39,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51873,
}
},
DownstreamScheme = "http",
@ -50,7 +50,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51873"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
@ -73,7 +73,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51873,
}
},
DownstreamScheme = "http",
@ -85,7 +85,7 @@ namespace Ocelot.AcceptanceTests
var requestId = Guid.NewGuid().ToString();
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51873"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/", requestId))
@ -108,7 +108,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51873,
}
},
DownstreamScheme = "http",
@ -124,7 +124,7 @@ namespace Ocelot.AcceptanceTests
var requestId = Guid.NewGuid().ToString();
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51873"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/", requestId))

View File

@ -298,7 +298,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51874,
}
},
UpstreamPathTemplate = "/vacancy/",
@ -315,7 +315,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51874,
}
},
UpstreamPathTemplate = "/vacancy/{vacancyId}",
@ -326,7 +326,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/api/v1/vacancy/1", 200, "Hello from Laura"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51874", "/api/v1/vacancy/1", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/vacancy/1"))

View File

@ -1,5 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
@ -336,7 +338,7 @@ namespace Ocelot.AcceptanceTests
/// <summary>
/// This is annoying cos it should be in the constructor but we need to set up the file before calling startup so its a step.
/// </summary>
public void GivenOcelotIsRunning(OcelotMiddlewareConfiguration ocelotMiddlewareConfig)
public void GivenOcelotIsRunning(OcelotPipelineConfiguration ocelotPipelineConfig)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
@ -373,7 +375,7 @@ namespace Ocelot.AcceptanceTests
})
.Configure(a =>
{
a.UseOcelot(ocelotMiddlewareConfig).Wait();
a.UseOcelot(ocelotPipelineConfig).Wait();
}));
_ocelotClient = _ocelotServer.CreateClient();
@ -552,7 +554,6 @@ namespace Ocelot.AcceptanceTests
_response.StatusCode.ShouldBe(expectedHttpStatusCode);
}
public void ThenTheStatusCodeShouldBe(int expectedHttpStatusCode)
{
var responseStatusCode = (int)_response.StatusCode;
@ -579,5 +580,51 @@ namespace Ocelot.AcceptanceTests
{
_response.Content.Headers.ContentLength.ShouldBe(expected);
}
public void WhenIMakeLotsOfDifferentRequestsToTheApiGateway()
{
int numberOfRequests = 100;
var aggregateUrl = "/";
var aggregateExpected = "{\"Laura\":{Hello from Laura},\"Tom\":{Hello from Tom}}";
var tomUrl = "/tom";
var tomExpected = "{Hello from Tom}";
var lauraUrl = "/laura";
var lauraExpected = "{Hello from Laura}";
var random = new Random();
var aggregateTasks = new Task[numberOfRequests];
for (int i = 0; i < numberOfRequests; i++)
{
aggregateTasks[i] = Fire(aggregateUrl, aggregateExpected, random);
}
var tomTasks = new Task[numberOfRequests];
for (int i = 0; i < numberOfRequests; i++)
{
tomTasks[i] = Fire(tomUrl, tomExpected, random);
}
var lauraTasks = new Task[numberOfRequests];
for (int i = 0; i < numberOfRequests; i++)
{
lauraTasks[i] = Fire(lauraUrl, lauraExpected, random);
}
Task.WaitAll(lauraTasks);
Task.WaitAll(tomTasks);
Task.WaitAll(aggregateTasks);
}
private async Task Fire(string url, string expectedBody, Random random)
{
var request = new HttpRequestMessage(new HttpMethod("GET"), url);
await Task.Delay(random.Next(0, 2));
var response = await _ocelotClient.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
content.ShouldBe(expectedBody);
}
}
}

View File

@ -39,7 +39,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51875,
}
},
UpstreamPathTemplate = "/",
@ -49,7 +49,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51875", "/", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
@ -75,7 +75,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51875,
}
},
UpstreamPathTemplate = "/",
@ -101,7 +101,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51875", "/", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
@ -142,7 +142,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51875,
}
},
UpstreamPathTemplate = "/",
@ -152,7 +152,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51875", "/", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
@ -192,7 +192,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51875,
}
},
UpstreamPathTemplate = "/",
@ -202,7 +202,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51875", "/", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
@ -227,7 +227,7 @@ namespace Ocelot.AcceptanceTests
new FileHostAndPort
{
Host = "localhost",
Port = 51879,
Port = 51875,
}
},
UpstreamPathTemplate = "/",
@ -237,7 +237,7 @@ namespace Ocelot.AcceptanceTests
}
};
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura"))
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51875", "/", 200, "Hello from Laura"))
.And(x => _steps.GivenThereIsAConfiguration(configuration))
.And(x => _steps.GivenOcelotIsRunning())
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))

View File

@ -18,7 +18,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.10.9" />
<PackageReference Include="BenchmarkDotNet" Version="0.10.12" />
</ItemGroup>
</Project>

View File

@ -17,7 +17,7 @@ namespace Ocelot.Benchmarks
Add(StatisticColumn.AllStatistics);
}
[Setup]
[GlobalSetup]
public void SetUp()
{
_urlPathMatcher = new RegExUrlMatcher();
@ -37,4 +37,4 @@ namespace Ocelot.Benchmarks
_urlPathMatcher.Match(_downstreamUrlPath, _downstreamUrlPathTemplate);
}
}
}
}

View File

@ -14,7 +14,7 @@
"HttpHandlerOptions": {
"AllowAutoRedirect": true,
"UseCookieContainer": true,
"UseTracing": true
"UseTracing": false
}
},
{
@ -99,7 +99,7 @@
"HttpHandlerOptions": {
"AllowAutoRedirect": true,
"UseCookieContainer": true,
"UseTracing": true
"UseTracing": false
},
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
@ -121,7 +121,7 @@
"HttpHandlerOptions": {
"AllowAutoRedirect": true,
"UseCookieContainer": true,
"UseTracing": true
"UseTracing": false
},
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,

View File

@ -1,6 +1,11 @@
namespace Ocelot.UnitTests.Authentication
using Ocelot.Configuration;
using Ocelot.Middleware;
namespace Ocelot.UnitTests.Authentication
{
using System.Collections.Generic;
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
@ -8,6 +13,7 @@
using Ocelot.Authentication.Middleware;
using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Logging;
using Ocelot.Responses;
@ -15,56 +21,75 @@
using TestStack.BDDfy;
using Xunit;
public class AuthenticationMiddlewareTests : ServerHostedMiddlewareTest
public class AuthenticationMiddlewareTests
{
private OkResponse<DownstreamRoute> _downstreamRoute;
private AuthenticationMiddleware _middleware;
private Mock<IOcelotLoggerFactory> _factory;
private Mock<IOcelotLogger> _logger;
private OcelotRequestDelegate _next;
private DownstreamContext _downstreamContext;
public AuthenticationMiddlewareTests()
{
GivenTheTestServerIsConfigured();
_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 => x.GivenTheDownStreamRouteIs(
new DownstreamRoute(
new List<PlaceholderNameAndValue>(),
new ReRouteBuilder().WithUpstreamHttpMethod(new List<string> { "Get" }).Build())))
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheUserIsAuthenticated())
this.Given(x => GivenTheDownStreamRouteIs(
new DownstreamReRouteBuilder().WithUpstreamHttpMethod(new List<string> { "Get" }).Build()))
.And(x => GivenTheTestServerPipelineIsConfigured())
.When(x => WhenICallTheMiddleware())
.Then(x => ThenTheUserIsAuthenticated())
.BDDfy();
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
private void WhenICallTheMiddleware()
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(ScopedRepository.Object);
_next = async (context) => {
byte[] byteArray = Encoding.ASCII.GetBytes("The user is authenticated");
MemoryStream stream = new MemoryStream(byteArray);
context.HttpContext.Response.Body = stream;
};
_middleware = new AuthenticationMiddleware(_next, _factory.Object);
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
private void GivenTheTestServerPipelineIsConfigured()
{
app.UseAuthenticationMiddleware();
app.Run(async x =>
{
await x.Response.WriteAsync("The user is authenticated");
});
_next = async (context) => {
byte[] byteArray = Encoding.ASCII.GetBytes("The user is authenticated");
MemoryStream stream = new MemoryStream(byteArray);
context.HttpContext.Response.Body = stream;
};
}
private void ThenTheUserIsAuthenticated()
{
var content = ResponseMessage.Content.ReadAsStringAsync().Result;
var content = _downstreamContext.HttpContext.Response.Body.AsString();
content.ShouldBe("The user is authenticated");
}
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
private void GivenTheDownStreamRouteIs(DownstreamReRoute downstreamRoute)
{
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
ScopedRepository
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
.Returns(_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;
};
}
}
}

View File

@ -1,9 +1,9 @@
namespace Ocelot.UnitTests.Authorization
using Ocelot.Middleware;
namespace Ocelot.UnitTests.Authorization
{
using System.Collections.Generic;
using System.Security.Claims;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Ocelot.Authorisation;
using Ocelot.Authorisation.Middleware;
@ -14,55 +14,57 @@
using Ocelot.Responses;
using TestStack.BDDfy;
using Xunit;
using Microsoft.AspNetCore.Http;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Configuration;
public class AuthorisationMiddlewareTests : ServerHostedMiddlewareTest
public class AuthorisationMiddlewareTests
{
private readonly Mock<IClaimsAuthoriser> _authService;
private readonly Mock<IScopesAuthoriser> _authScopesService;
private OkResponse<DownstreamRoute> _downstreamRoute;
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>();
GivenTheTestServerIsConfigured();
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
_next = async context => {
//do nothing
};
_middleware = new AuthorisationMiddleware(_next, _authService.Object, _authScopesService.Object, _loggerFactory.Object);
}
[Fact]
public void should_call_authorisation_service()
{
this.Given(x => x.GivenTheDownStreamRouteIs(new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
this.Given(x => x.GivenTheDownStreamRouteIs(new List<PlaceholderNameAndValue>(),
new DownstreamReRouteBuilder()
.WithIsAuthorised(true)
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.Build()))
.And(x => x.GivenTheAuthServiceReturns(new OkResponse<bool>(true)))
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheAuthServiceIsCalledCorrectly())
.BDDfy();
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
private void WhenICallTheMiddleware()
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(_authService.Object);
services.AddSingleton(_authScopesService.Object);
services.AddSingleton(ScopedRepository.Object);
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
private void GivenTheDownStreamRouteIs(List<PlaceholderNameAndValue> templatePlaceholderNameAndValues, DownstreamReRoute downstreamReRoute)
{
app.UseAuthorisationMiddleware();
}
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
{
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
ScopedRepository
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
.Returns(_downstreamRoute);
_downstreamContext.TemplatePlaceholderNameAndValues = templatePlaceholderNameAndValues;
_downstreamContext.DownstreamReRoute = downstreamReRoute;
}
private void GivenTheAuthServiceReturns(Response<bool> expected)

View File

@ -1,4 +1,6 @@
using Ocelot.Infrastructure.RequestData;
using Ocelot.Errors;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Middleware;
namespace Ocelot.UnitTests.Cache
{
@ -22,20 +24,37 @@ namespace Ocelot.UnitTests.Cache
using Ocelot.Responses;
using TestStack.BDDfy;
using Xunit;
using Ocelot.DownstreamRouteFinder.Middleware;
using Microsoft.AspNetCore.Http;
public class OutputCacheMiddlewareRealCacheTests : ServerHostedMiddlewareTest
public class OutputCacheMiddlewareRealCacheTests
{
private IOcelotCache<CachedResponse> _cacheManager;
private CachedResponse _response;
private IRequestScopedDataRepository _repo;
private OutputCacheMiddleware _middleware;
private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private IRegionCreator _regionCreator;
private Mock<IOcelotLogger> _logger;
public OutputCacheMiddlewareRealCacheTests()
{
ScopedRepository
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
.Returns(new OkResponse<HttpRequestMessage>(new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123")));
GivenTheTestServerIsConfigured();
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<OutputCacheMiddleware>()).Returns(_logger.Object);
_regionCreator = new RegionCreator();
var cacheManagerOutputCache = CacheFactory.Build<CachedResponse>("OcelotOutputCache", x =>
{
x.WithDictionaryHandle();
});
_cacheManager = new OcelotCacheManagerCache<CachedResponse>(cacheManagerOutputCache);
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
_downstreamContext.DownstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123");
_next = async context => {
//do nothing..
};
_middleware = new OutputCacheMiddleware(_next, _loggerFactory.Object, _cacheManager, _regionCreator);
}
[Fact]
@ -54,12 +73,16 @@ namespace Ocelot.UnitTests.Cache
this.Given(x => x.GivenResponseIsNotCached(response))
.And(x => x.GivenTheDownstreamRouteIs())
.And(x => x.GivenThereAreNoErrors())
.And(x => x.GivenThereIsADownstreamUrl())
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheContentTypeHeaderIsCached())
.BDDfy();
}
private void WhenICallTheMiddleware()
{
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void ThenTheContentTypeHeaderIsCached()
{
var result = _cacheManager.Get("GET-https://some.url/blah?abcd=123", "kanken");
@ -67,65 +90,25 @@ namespace Ocelot.UnitTests.Cache
header.First().ShouldBe("application/json");
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
{
var cacheManagerOutputCache = CacheFactory.Build<CachedResponse>("OcelotOutputCache", x =>
{
x.WithDictionaryHandle();
});
_cacheManager = new OcelotCacheManagerCache<CachedResponse>(cacheManagerOutputCache);
services.AddSingleton<ICacheManager<CachedResponse>>(cacheManagerOutputCache);
services.AddSingleton<IOcelotCache<CachedResponse>>(_cacheManager);
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(_cacheManager);
services.AddSingleton(ScopedRepository.Object);
services.AddSingleton<IRegionCreator, RegionCreator>();
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseOutputCacheMiddleware();
}
private void GivenResponseIsNotCached(HttpResponseMessage message)
{
ScopedRepository
.Setup(x => x.Get<HttpResponseMessage>("HttpResponseMessage"))
.Returns(new OkResponse<HttpResponseMessage>(message));
_downstreamContext.DownstreamResponse = message;
}
private void GivenTheDownstreamRouteIs()
{
var reRoute = new ReRouteBuilder()
var reRoute = new DownstreamReRouteBuilder()
.WithIsCached(true)
.WithCacheOptions(new CacheOptions(100, "kanken"))
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build();
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(), reRoute);
ScopedRepository
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
.Returns(new OkResponse<DownstreamRoute>(downstreamRoute));
_downstreamContext.DownstreamReRoute = reRoute;
}
private void GivenThereAreNoErrors()
{
ScopedRepository
.Setup(x => x.Get<bool>("OcelotMiddlewareError"))
.Returns(new OkResponse<bool>(false));
}
private void GivenThereIsADownstreamUrl()
{
ScopedRepository
.Setup(x => x.Get<string>("DownstreamUrl"))
.Returns(new OkResponse<string>("anything"));
_downstreamContext.Errors = new List<Error>();
}
}
}

View File

@ -1,4 +1,6 @@
using System.Net;
using Ocelot.Errors;
using Ocelot.Middleware;
namespace Ocelot.UnitTests.Cache
{
@ -6,6 +8,7 @@ namespace Ocelot.UnitTests.Cache
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Ocelot.Cache;
@ -13,26 +16,37 @@ namespace Ocelot.UnitTests.Cache
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Logging;
using Ocelot.Responses;
using TestStack.BDDfy;
using Xunit;
public class OutputCacheMiddlewareTests : ServerHostedMiddlewareTest
public class OutputCacheMiddlewareTests
{
private readonly Mock<IOcelotCache<CachedResponse>> _cacheManager;
private readonly Mock<IOcelotCache<CachedResponse>> _cacheManager;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger;
private OutputCacheMiddleware _middleware;
private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
private CachedResponse _response;
private IRegionCreator _regionCreator;
public OutputCacheMiddlewareTests()
{
_cacheManager = new Mock<IOcelotCache<CachedResponse>>();
_regionCreator = new RegionCreator();
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<OutputCacheMiddleware>()).Returns(_logger.Object);
_next = async context => {
//do nothing
};
ScopedRepository
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
.Returns(new OkResponse<HttpRequestMessage>(new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123")));
GivenTheTestServerIsConfigured();
_downstreamContext.DownstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123");
}
[Fact]
@ -41,7 +55,6 @@ namespace Ocelot.UnitTests.Cache
var cachedResponse = new CachedResponse(HttpStatusCode.OK, new Dictionary<string, IEnumerable<string>>(), "", new Dictionary<string, IEnumerable<string>>());
this.Given(x => x.GivenThereIsACachedResponse(cachedResponse))
.And(x => x.GivenTheDownstreamRouteIs())
.And(x => x.GivenThereIsADownstreamUrl())
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheCacheGetIsCalledCorrectly())
.BDDfy();
@ -53,24 +66,15 @@ namespace Ocelot.UnitTests.Cache
this.Given(x => x.GivenResponseIsNotCached())
.And(x => x.GivenTheDownstreamRouteIs())
.And(x => x.GivenThereAreNoErrors())
.And(x => x.GivenThereIsADownstreamUrl())
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheCacheAddIsCalledCorrectly())
.BDDfy();
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
private void WhenICallTheMiddleware()
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(_cacheManager.Object);
services.AddSingleton(ScopedRepository.Object);
services.AddSingleton<IRegionCreator, RegionCreator>();
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseOutputCacheMiddleware();
_middleware = new OutputCacheMiddleware(_next, _loggerFactory.Object, _cacheManager.Object, _regionCreator);
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void GivenThereIsACachedResponse(CachedResponse response)
@ -83,38 +87,30 @@ namespace Ocelot.UnitTests.Cache
private void GivenResponseIsNotCached()
{
ScopedRepository
.Setup(x => x.Get<HttpResponseMessage>("HttpResponseMessage"))
.Returns(new OkResponse<HttpResponseMessage>(new HttpResponseMessage()));
_downstreamContext.DownstreamResponse = new HttpResponseMessage();
}
private void GivenTheDownstreamRouteIs()
{
var reRoute = new ReRouteBuilder()
.WithIsCached(true)
.WithCacheOptions(new CacheOptions(100, "kanken"))
.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);
ScopedRepository
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
.Returns(new OkResponse<DownstreamRoute>(downstreamRoute));
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
}
private void GivenThereAreNoErrors()
{
ScopedRepository
.Setup(x => x.Get<bool>("OcelotMiddlewareError"))
.Returns(new OkResponse<bool>(false));
}
_downstreamContext.Errors = new List<Error>();
private void GivenThereIsADownstreamUrl()
{
ScopedRepository
.Setup(x => x.Get<string>("DownstreamUrl"))
.Returns(new OkResponse<string>("anything"));
}
private void ThenTheCacheGetIsCalledCorrectly()

View File

@ -1,9 +1,9 @@
namespace Ocelot.UnitTests.Claims
using Ocelot.Middleware;
namespace Ocelot.UnitTests.Claims
{
using System.Collections.Generic;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Ocelot.Claims;
using Ocelot.Claims.Middleware;
@ -15,17 +15,29 @@
using Ocelot.Responses;
using TestStack.BDDfy;
using Xunit;
using Ocelot.DownstreamRouteFinder.Middleware;
public class ClaimsBuilderMiddlewareTests : ServerHostedMiddlewareTest
public class ClaimsBuilderMiddlewareTests
{
private readonly Mock<IAddClaimsToRequest> _addHeaders;
private Response<DownstreamRoute> _downstreamRoute;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger;
private readonly ClaimsBuilderMiddleware _middleware;
private readonly DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
public ClaimsBuilderMiddlewareTests()
{
_addHeaders = new Mock<IAddClaimsToRequest>();
GivenTheTestServerIsConfigured();
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<ClaimsBuilderMiddleware>()).Returns(_logger.Object);
_next = async context => {
//do nothing
};
_middleware = new ClaimsBuilderMiddleware(_next, _loggerFactory.Object, _addHeaders.Object);
}
[Fact]
@ -33,11 +45,14 @@
{
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithClaimsToClaims(new List<ClaimToThing>
{
new ClaimToThing("sub", "UserType", "|", 0)
})
.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());
@ -48,25 +63,16 @@
.BDDfy();
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
private void WhenICallTheMiddleware()
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(_addHeaders.Object);
services.AddSingleton(ScopedRepository.Object);
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseClaimsBuilderMiddleware();
}
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
{
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
ScopedRepository
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
.Returns(_downstreamRoute);
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
}
private void GivenTheAddClaimsToRequestReturns()

View File

@ -20,7 +20,7 @@ namespace Ocelot.UnitTests.Configuration
private readonly IConfigurationValidator _configurationValidator;
private FileConfiguration _fileConfiguration;
private Response<ConfigurationValidationResult> _result;
private Mock<IAuthenticationSchemeProvider> _provider;
private readonly Mock<IAuthenticationSchemeProvider> _provider;
public ConfigurationFluentValidationTests()
{
@ -28,6 +28,373 @@ namespace Ocelot.UnitTests.Configuration
_configurationValidator = new FileConfigurationFluentValidator(_provider.Object);
}
[Fact]
public void configuration_is_valid_if_aggregates_are_valid()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51878,
}
},
UpstreamPathTemplate = "/laura",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Laura"
},
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51880,
}
},
UpstreamPathTemplate = "/tom",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Tom"
}
},
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
UpstreamPathTemplate = "/",
UpstreamHost = "localhost",
ReRouteKeys = new List<string>
{
"Tom",
"Laura"
}
}
}
};
this.Given(x => x.GivenAConfiguration(configuration))
.When(x => x.WhenIValidateTheConfiguration())
.Then(x => x.ThenTheResultIsValid())
.BDDfy();
}
[Fact]
public void configuration_is_invalid_if_aggregates_are_duplicate_of_re_routes()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51878,
}
},
UpstreamPathTemplate = "/laura",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Laura"
},
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51880,
}
},
UpstreamPathTemplate = "/tom",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Tom",
UpstreamHost = "localhost"
}
},
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
UpstreamPathTemplate = "/tom",
UpstreamHost = "localhost",
ReRouteKeys = new List<string>
{
"Tom",
"Laura"
},
}
}
};
this.Given(x => x.GivenAConfiguration(configuration))
.When(x => x.WhenIValidateTheConfiguration())
.Then(x => x.ThenTheResultIsNotValid())
.And(x => x.ThenTheErrorMessageAtPositionIs(0, "reRoute /tom has duplicate aggregate"))
.BDDfy();
}
[Fact]
public void configuration_is_valid_if_aggregates_are_not_duplicate_of_re_routes()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51878,
}
},
UpstreamPathTemplate = "/laura",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Laura"
},
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51880,
}
},
UpstreamPathTemplate = "/tom",
UpstreamHttpMethod = new List<string> { "Post" },
Key = "Tom",
UpstreamHost = "localhost"
}
},
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
UpstreamPathTemplate = "/tom",
UpstreamHost = "localhost",
ReRouteKeys = new List<string>
{
"Tom",
"Laura"
},
}
}
};
this.Given(x => x.GivenAConfiguration(configuration))
.When(x => x.WhenIValidateTheConfiguration())
.Then(x => x.ThenTheResultIsValid())
.BDDfy();
}
[Fact]
public void configuration_is_invalid_if_aggregates_are_duplicate_of_aggregates()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51878,
}
},
UpstreamPathTemplate = "/laura",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Laura"
},
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51880,
}
},
UpstreamPathTemplate = "/lol",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Tom"
}
},
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
UpstreamPathTemplate = "/tom",
UpstreamHost = "localhost",
ReRouteKeys = new List<string>
{
"Tom",
"Laura"
}
},
new FileAggregateReRoute
{
UpstreamPathTemplate = "/tom",
UpstreamHost = "localhost",
ReRouteKeys = new List<string>
{
"Tom",
"Laura"
}
}
}
};
this.Given(x => x.GivenAConfiguration(configuration))
.When(x => x.WhenIValidateTheConfiguration())
.Then(x => x.ThenTheResultIsNotValid())
.And(x => x.ThenTheErrorMessageAtPositionIs(0, "aggregate /tom has duplicate aggregate"))
.BDDfy();
}
[Fact]
public void configuration_is_invalid_if_re_routes_dont_exist_for_aggregate()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51878,
}
},
UpstreamPathTemplate = "/laura",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Laura"
}
},
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
UpstreamPathTemplate = "/",
UpstreamHost = "localhost",
ReRouteKeys = new List<string>
{
"Tom",
"Laura"
}
}
}
};
this.Given(x => x.GivenAConfiguration(configuration))
.When(x => x.WhenIValidateTheConfiguration())
.Then(x => x.ThenTheResultIsNotValid())
.And(x => x.ThenTheErrorMessageAtPositionIs(0, "ReRoutes for aggregateReRoute / either do not exist or do not have correct Key property"))
.BDDfy();
}
[Fact]
public void configuration_is_invalid_if_aggregate_has_re_routes_with_specific_request_id_keys()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51878,
}
},
UpstreamPathTemplate = "/laura",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Laura"
},
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51880,
}
},
UpstreamPathTemplate = "/tom",
UpstreamHttpMethod = new List<string> { "Get" },
RequestIdKey = "should_fail",
Key = "Tom"
}
},
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
UpstreamPathTemplate = "/",
UpstreamHost = "localhost",
ReRouteKeys = new List<string>
{
"Tom",
"Laura"
}
}
}
};
this.Given(x => x.GivenAConfiguration(configuration))
.When(x => x.WhenIValidateTheConfiguration())
.Then(x => x.ThenTheResultIsNotValid())
.And(x => x.ThenTheErrorMessageAtPositionIs(0, "aggregateReRoute / contains ReRoute with specific RequestIdKey, this is not possible with Aggregates"))
.BDDfy();
}
[Fact]
public void configuration_is_invalid_if_scheme_in_downstream_or_upstream_template()
{

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using Castle.Components.DictionaryAdapter;
using Microsoft.Extensions.Options;
using Moq;
using Ocelot.Cache;
@ -81,6 +82,125 @@ namespace Ocelot.UnitTests.Configuration
_downstreamAddressesCreator.Object);
}
[Fact]
public void should_set_up_aggregate_re_route()
{
var configuration = new FileConfiguration
{
ReRoutes = new List<FileReRoute>
{
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51878,
}
},
UpstreamPathTemplate = "/laura",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Laura",
UpstreamHost = "localhost"
},
new FileReRoute
{
DownstreamPathTemplate = "/",
DownstreamScheme = "http",
DownstreamHostAndPorts = new List<FileHostAndPort>
{
new FileHostAndPort
{
Host = "localhost",
Port = 51880,
}
},
UpstreamPathTemplate = "/tom",
UpstreamHttpMethod = new List<string> { "Get" },
Key = "Tom",
UpstreamHost = "localhost",
}
},
Aggregates = new List<FileAggregateReRoute>
{
new FileAggregateReRoute
{
UpstreamPathTemplate = "/",
UpstreamHost = "localhost",
ReRouteKeys = new List<string>
{
"Tom",
"Laura"
}
}
}
};
var serviceProviderConfig = new ServiceProviderConfigurationBuilder().Build();
var expected = new List<ReRoute>();
var lauraDownstreamReRoute = new DownstreamReRouteBuilder()
.WithUpstreamHost("localhost")
.WithKey("Laura")
.WithDownstreamPathTemplate("/")
.WithDownstreamScheme("http")
.WithUpstreamHttpMethod(new List<string>() {"Get"})
.WithDownstreamAddresses(new List<DownstreamHostAndPort>() {new DownstreamHostAndPort("localhost", 51878)})
.Build();
var lauraReRoute = new ReRouteBuilder()
.WithUpstreamHttpMethod(new List<string>() { "Get" })
.WithUpstreamHost("localhost")
.WithUpstreamPathTemplate("/laura")
.WithDownstreamReRoute(lauraDownstreamReRoute)
.Build();
expected.Add(lauraReRoute);
var tomDownstreamReRoute = new DownstreamReRouteBuilder()
.WithUpstreamHost("localhost")
.WithKey("Tom")
.WithDownstreamPathTemplate("/")
.WithDownstreamScheme("http")
.WithUpstreamHttpMethod(new List<string>() { "Get" })
.WithDownstreamAddresses(new List<DownstreamHostAndPort>() { new DownstreamHostAndPort("localhost", 51878) })
.Build();
var tomReRoute = new ReRouteBuilder()
.WithUpstreamHttpMethod(new List<string>() { "Get" })
.WithUpstreamHost("localhost")
.WithUpstreamPathTemplate("/tom")
.WithDownstreamReRoute(tomDownstreamReRoute)
.Build();
expected.Add(tomReRoute);
var aggregateReReRoute = new ReRouteBuilder()
.WithUpstreamPathTemplate("/")
.WithUpstreamHost("localhost")
.WithDownstreamReRoute(lauraDownstreamReRoute)
.WithDownstreamReRoute(tomDownstreamReRoute)
.WithUpstreamHttpMethod(new List<string>() { "Get" })
.Build();
expected.Add(aggregateReReRoute);
this.Given(x => x.GivenTheConfigIs(configuration))
.And(x => x.GivenTheFollowingOptionsAreReturned(new ReRouteOptionsBuilder().Build()))
.And(x => x.GivenTheFollowingIsReturned(serviceProviderConfig))
.And(x => GivenTheDownstreamAddresses())
.And(x => GivenTheHeaderFindAndReplaceCreatorReturns())
.And(x => x.GivenTheConfigIsValid())
.When(x => x.WhenICreateTheConfig())
.Then(x => x.ThenTheServiceProviderCreatorIsCalledCorrectly())
.Then(x => x.ThenTheReRoutesAre(expected))
.BDDfy();
}
[Fact]
public void should_call_service_provider_config_creator()
{
@ -234,6 +354,13 @@ namespace Ocelot.UnitTests.Configuration
var reRouteOptions = new ReRouteOptionsBuilder()
.Build();
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamAddresses(new List<DownstreamHostAndPort>() {new DownstreamHostAndPort("127.0.0.1", 80)})
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> {"Get"})
.Build();
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
@ -261,8 +388,7 @@ namespace Ocelot.UnitTests.Configuration
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamAddresses(new List<DownstreamHostAndPort>(){new DownstreamHostAndPort("127.0.0.1", 80) })
.WithDownstreamPathTemplate("/products/{productId}")
.WithDownstreamReRoute(downstreamReRoute)
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()
@ -276,6 +402,13 @@ namespace Ocelot.UnitTests.Configuration
var reRouteOptions = new ReRouteOptionsBuilder()
.Build();
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamScheme("https")
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> {"Get"})
.Build();
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
@ -297,8 +430,7 @@ namespace Ocelot.UnitTests.Configuration
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamScheme("https")
.WithDownstreamPathTemplate("/products/{productId}")
.WithDownstreamReRoute(downstreamReRoute)
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()
@ -312,6 +444,14 @@ namespace Ocelot.UnitTests.Configuration
var reRouteOptions = new ReRouteOptionsBuilder()
.Build();
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> {"Get"})
.WithUseServiceDiscovery(true)
.WithServiceName("ProductService")
.Build();
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
@ -341,11 +481,9 @@ namespace Ocelot.UnitTests.Configuration
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithDownstreamReRoute(downstreamReRoute)
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUseServiceDiscovery(true)
.WithServiceName("ProductService")
.Build()
}))
.BDDfy();
@ -356,7 +494,15 @@ namespace Ocelot.UnitTests.Configuration
{
var reRouteOptions = new ReRouteOptionsBuilder()
.Build();
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> {"Get"})
.WithUseServiceDiscovery(false)
.Build();
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
@ -378,10 +524,9 @@ namespace Ocelot.UnitTests.Configuration
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithDownstreamReRoute(downstreamReRoute)
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUseServiceDiscovery(false)
.Build()
}))
.BDDfy();
@ -392,7 +537,15 @@ namespace Ocelot.UnitTests.Configuration
{
var reRouteOptions = new ReRouteOptionsBuilder()
.Build();
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> {"Get"})
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("(?i)/api/products/.*/$", 1))
.Build();
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
@ -415,7 +568,7 @@ namespace Ocelot.UnitTests.Configuration
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithDownstreamReRoute(downstreamReRoute)
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("(?i)/api/products/.*/$", 1))
@ -430,6 +583,13 @@ namespace Ocelot.UnitTests.Configuration
var reRouteOptions = new ReRouteOptionsBuilder()
.Build();
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> {"Get"})
.WithRequestIdKey("blahhhh")
.Build();
this.Given(x => x.GivenTheConfigIs(new FileConfiguration
{
ReRoutes = new List<FileReRoute>
@ -456,10 +616,9 @@ namespace Ocelot.UnitTests.Configuration
.Then(x => x.ThenTheReRoutesAre(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithDownstreamReRoute(downstreamReRoute)
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithRequestIdKey("blahhhh")
.Build()
}))
.And(x => x.ThenTheRequestIdKeyCreatorIsCalledCorrectly())
@ -514,17 +673,23 @@ namespace Ocelot.UnitTests.Configuration
.WithAllowedScopes(new List<string>())
.Build();
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> {"Get"})
.WithAuthenticationOptions(authenticationOptions)
.WithClaimsToHeaders(new List<ClaimToThing>
{
new ClaimToThing("CustomerId", "CustomerId", "", 0),
})
.Build();
var expected = new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithDownstreamReRoute(downstreamReRoute)
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithAuthenticationOptions(authenticationOptions)
.WithClaimsToHeaders(new List<ClaimToThing>
{
new ClaimToThing("CustomerId", "CustomerId", "", 0),
})
.Build()
};
@ -554,13 +719,19 @@ namespace Ocelot.UnitTests.Configuration
.WithAllowedScopes(new List<string>())
.Build();
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> {"Get"})
.WithAuthenticationOptions(authenticationOptions)
.Build();
var expected = new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("/products/{productId}")
.WithDownstreamReRoute(downstreamReRoute)
.WithUpstreamPathTemplate("/api/products/{productId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithAuthenticationOptions(authenticationOptions)
.Build()
};
@ -643,14 +814,16 @@ namespace Ocelot.UnitTests.Configuration
var result = _config.Data.ReRoutes[i];
var expected = expectedReRoutes[i];
result.DownstreamPathTemplate.Value.ShouldBe(expected.DownstreamPathTemplate.Value);
result.DownstreamReRoute.Count.ShouldBe(expected.DownstreamReRoute.Count);
result.DownstreamReRoute[0].DownstreamPathTemplate.Value.ShouldBe(expected.DownstreamReRoute[0].DownstreamPathTemplate.Value);
result.UpstreamHttpMethod.ShouldBe(expected.UpstreamHttpMethod);
result.UpstreamPathTemplate.Value.ShouldBe(expected.UpstreamPathTemplate.Value);
result.UpstreamTemplatePattern?.Template.ShouldBe(expected.UpstreamTemplatePattern?.Template);
result.ClaimsToClaims.Count.ShouldBe(expected.ClaimsToClaims.Count);
result.ClaimsToHeaders.Count.ShouldBe(expected.ClaimsToHeaders.Count);
result.ClaimsToQueries.Count.ShouldBe(expected.ClaimsToQueries.Count);
result.RequestIdKey.ShouldBe(expected.RequestIdKey);
result.DownstreamReRoute[0].ClaimsToClaims.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToClaims.Count);
result.DownstreamReRoute[0].ClaimsToHeaders.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToHeaders.Count);
result.DownstreamReRoute[0].ClaimsToQueries.Count.ShouldBe(expected.DownstreamReRoute[0].ClaimsToQueries.Count);
result.DownstreamReRoute[0].RequestIdKey.ShouldBe(expected.DownstreamReRoute[0].RequestIdKey);
}
}
@ -659,8 +832,8 @@ namespace Ocelot.UnitTests.Configuration
{
for (int i = 0; i < _config.Data.ReRoutes.Count; i++)
{
var result = _config.Data.ReRoutes[i].AuthenticationOptions;
var expected = expectedReRoutes[i].AuthenticationOptions;
var result = _config.Data.ReRoutes[i].DownstreamReRoute[0].AuthenticationOptions;
var expected = expectedReRoutes[i].DownstreamReRoute[0].AuthenticationOptions;
result.AllowedScopes.ShouldBe(expected.AllowedScopes);
}
}
@ -714,10 +887,10 @@ namespace Ocelot.UnitTests.Configuration
private void ThenTheQosOptionsAre(QoSOptions qosOptions)
{
_config.Data.ReRoutes[0].QosOptionsOptions.DurationOfBreak.ShouldBe(qosOptions.DurationOfBreak);
_config.Data.ReRoutes[0].DownstreamReRoute[0].QosOptionsOptions.DurationOfBreak.ShouldBe(qosOptions.DurationOfBreak);
_config.Data.ReRoutes[0].QosOptionsOptions.ExceptionsAllowedBeforeBreaking.ShouldBe(qosOptions.ExceptionsAllowedBeforeBreaking);
_config.Data.ReRoutes[0].QosOptionsOptions.TimeoutValue.ShouldBe(qosOptions.TimeoutValue);
_config.Data.ReRoutes[0].DownstreamReRoute[0].QosOptionsOptions.ExceptionsAllowedBeforeBreaking.ShouldBe(qosOptions.ExceptionsAllowedBeforeBreaking);
_config.Data.ReRoutes[0].DownstreamReRoute[0].QosOptionsOptions.TimeoutValue.ShouldBe(qosOptions.TimeoutValue);
}
private void ThenTheServiceProviderCreatorIsCalledCorrectly()

View File

@ -44,7 +44,7 @@ namespace Ocelot.UnitTests.Configuration
private void ThenTheConfigurationIsReturned()
{
_getResult.Data.ReRoutes[0].DownstreamPathTemplate.Value.ShouldBe("initial");
_getResult.Data.ReRoutes[0].DownstreamReRoute[0].DownstreamPathTemplate.Value.ShouldBe("initial");
}
private void WhenIGetTheConfiguration()
@ -83,13 +83,24 @@ namespace Ocelot.UnitTests.Configuration
AdministrationPath = administrationPath;
}
public List<ReRoute> ReRoutes => new List<ReRoute>
public List<ReRoute> ReRoutes
{
new ReRouteBuilder()
.WithDownstreamPathTemplate(_downstreamTemplatePath)
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build()
};
get
{
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate(_downstreamTemplatePath)
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build();
return new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamReRoute(downstreamReRoute)
.WithUpstreamHttpMethod(new List<string> {"Get"})
.Build()
};
}
}
public string AdministrationPath {get;}

View File

@ -1,7 +1,11 @@
namespace Ocelot.UnitTests.DownstreamRouteFinder
using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer;
namespace Ocelot.UnitTests.DownstreamRouteFinder
{
using System.Collections.Generic;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Ocelot.Configuration;
@ -13,22 +17,36 @@
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Logging;
using Ocelot.Responses;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
public class DownstreamRouteFinderMiddlewareTests : ServerHostedMiddlewareTest
public class DownstreamRouteFinderMiddlewareTests
{
private readonly Mock<IDownstreamRouteFinder> _downstreamRouteFinder;
private readonly Mock<IDownstreamRouteFinder> _finder;
private readonly Mock<IOcelotConfigurationProvider> _provider;
private Response<DownstreamRoute> _downstreamRoute;
private IOcelotConfiguration _config;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger;
private DownstreamRouteFinderMiddleware _middleware;
private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
private readonly Mock<IMultiplexer> _multiplexer;
public DownstreamRouteFinderMiddlewareTests()
{
_provider = new Mock<IOcelotConfigurationProvider>();
_downstreamRouteFinder = new Mock<IDownstreamRouteFinder>();
GivenTheTestServerIsConfigured();
_finder = new Mock<IDownstreamRouteFinder>();
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<DownstreamRouteFinderMiddleware>()).Returns(_logger.Object);
_next = async context => {
//do nothing
};
_multiplexer = new Mock<IMultiplexer>();
_middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _finder.Object, _provider.Object, _multiplexer.Object);
}
[Fact]
@ -36,11 +54,16 @@
{
var config = new OcelotConfiguration(null, null, new ServiceProviderConfigurationBuilder().Build(), "");
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithUpstreamHttpMethod(new List<string> {"Get"})
.Build();
this.Given(x => x.GivenTheDownStreamRouteFinderReturns(
new DownstreamRoute(
new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithDownstreamReRoute(downstreamReRoute)
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.And(x => GivenTheFollowingConfig(config))
@ -49,6 +72,11 @@
.BDDfy();
}
private void WhenICallTheMiddleware()
{
_middleware.Invoke(_downstreamContext).GetAwaiter().GetType();
}
private void GivenTheFollowingConfig(IOcelotConfiguration config)
{
_config = config;
@ -57,35 +85,18 @@
.ReturnsAsync(new OkResponse<IOcelotConfiguration>(_config));
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(_downstreamRouteFinder.Object);
services.AddSingleton(_provider.Object);
services.AddSingleton(ScopedRepository.Object);
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseDownstreamRouteFinderMiddleware();
}
private void GivenTheDownStreamRouteFinderReturns(DownstreamRoute downstreamRoute)
{
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
_downstreamRouteFinder
_finder
.Setup(x => x.FindDownstreamRoute(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<IOcelotConfiguration>(), It.IsAny<string>()))
.Returns(_downstreamRoute);
}
private void ThenTheScopedDataRepositoryIsCalledCorrectly()
{
ScopedRepository
.Verify(x => x.Add("DownstreamRoute", _downstreamRoute.Data), Times.Once());
ScopedRepository
.Verify(x => x.Add("ServiceProviderConfiguration", _config.ServiceProviderConfiguration), Times.Once());
_downstreamContext.TemplatePlaceholderNameAndValues.ShouldBe(_downstreamRoute.Data.TemplatePlaceholderNameAndValues);
_downstreamContext.ServiceProviderConfiguration.ShouldBe(_config.ServiceProviderConfiguration);
}
}
}

View File

@ -47,13 +47,23 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
.Build(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0))
@ -64,7 +74,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.When(x => x.WhenICallTheFinder())
.Then(x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
.Build())
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
@ -84,13 +99,23 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 0))
.Build(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
@ -101,7 +126,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.When(x => x.WhenICallTheFinder())
.Then(x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
.WithUpstreamHttpMethod(new List<string> { "Post" })
.Build())
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("test", 1))
.WithUpstreamHttpMethod(new List<string> { "Post" })
.Build()
@ -121,7 +150,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
@ -135,7 +169,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(
new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build()
@ -157,7 +195,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
@ -171,7 +214,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(
new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build()
@ -193,7 +240,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
@ -206,7 +258,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.Then(
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build()
@ -227,13 +283,23 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
.Build(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPathForAPost")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPathForAPost")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
@ -246,7 +312,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.Then(
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPathForAPost")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPathForAPost")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
.Build())
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
.Build()
@ -263,7 +333,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("somPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("somPath")
.WithUpstreamPathTemplate("somePath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("somePath", 1))
.Build())
.WithUpstreamPathTemplate("somePath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("somePath", 1))
@ -292,7 +367,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get", "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get", "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
@ -305,7 +385,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.Then(
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
.Build())
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
.Build()
@ -326,7 +410,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string>())
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string>())
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
@ -339,7 +428,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.Then(
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
.Build())
.WithUpstreamHttpMethod(new List<string> { "Post" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
.Build()
@ -360,7 +453,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get", "Patch", "Delete" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get", "Patch", "Delete" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("", 1))
@ -388,7 +486,13 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.WithUpstreamHost("MATCH")
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
@ -403,7 +507,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(
new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build()
@ -425,7 +533,12 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
@ -439,7 +552,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(
new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build()
@ -459,12 +576,17 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.WithUpstreamHost("MATCH")
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.WithUpstreamHost("MATCH")
.Build()
}, string.Empty, serviceProviderConfig
))
@ -490,13 +612,24 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
.And(x => x.GivenTheConfigurationIs(new List<ReRoute>
{
new ReRouteBuilder()
.WithDownstreamPathTemplate("THENULLPATH")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("THENULLPATH")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.WithUpstreamHost("MATCH")
.Build())
.WithUpstreamPathTemplate("someUpstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
@ -511,7 +644,11 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
x => x.ThenTheFollowingIsReturned(new DownstreamRoute(
new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("someDownstreamPath")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamTemplatePattern(new UpstreamPathTemplate("someUpstreamPath", 1))
.Build()
@ -592,7 +729,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
private void ThenTheFollowingIsReturned(DownstreamRoute expected)
{
_result.Data.ReRoute.DownstreamPathTemplate.Value.ShouldBe(expected.ReRoute.DownstreamPathTemplate.Value);
_result.Data.ReRoute.DownstreamReRoute[0].DownstreamPathTemplate.Value.ShouldBe(expected.ReRoute.DownstreamReRoute[0].DownstreamPathTemplate.Value);
_result.Data.ReRoute.UpstreamTemplatePattern.Priority.ShouldBe(expected.ReRoute.UpstreamTemplatePattern.Priority);
for (int i = 0; i < _result.Data.TemplatePlaceholderNameAndValues.Count; i++)

View File

@ -1,4 +1,6 @@
namespace Ocelot.UnitTests.DownstreamUrlCreator
using Ocelot.Middleware;
namespace Ocelot.UnitTests.DownstreamUrlCreator
{
using System;
using System.Collections.Generic;
@ -19,39 +21,49 @@
using TestStack.BDDfy;
using Xunit;
using Shouldly;
using Ocelot.DownstreamRouteFinder.Middleware;
using Microsoft.AspNetCore.Http;
public class DownstreamUrlCreatorMiddlewareTests : ServerHostedMiddlewareTest
public class DownstreamUrlCreatorMiddlewareTests
{
private readonly Mock<IDownstreamPathPlaceholderReplacer> _downstreamUrlTemplateVariableReplacer;
private readonly Mock<IUrlBuilder> _urlBuilder;
private Response<DownstreamRoute> _downstreamRoute;
private OkResponse<DownstreamPath> _downstreamPath;
private HttpRequestMessage _downstreamRequest;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger;
private DownstreamUrlCreatorMiddleware _middleware;
private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
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>();
_urlBuilder = new Mock<IUrlBuilder>();
_downstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://my.url/abc/?q=123");
ScopedRepository
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
GivenTheTestServerIsConfigured();
_downstreamContext.DownstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://my.url/abc/?q=123");
_next = async context => {
//do nothing
};
}
[Fact]
public void should_replace_scheme_and_path()
{
var downstreamReRoute = new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithUpstreamHttpMethod(new List<string> {"Get"})
.WithDownstreamScheme("https")
.Build();
this.Given(x => x.GivenTheDownStreamRouteIs(
new DownstreamRoute(
new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithDownstreamReRoute(downstreamReRoute)
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithDownstreamScheme("https")
.Build())))
.And(x => x.GivenTheDownstreamRequestUriIs("http://my.url/abc?q=123"))
.And(x => x.GivenTheUrlReplacerWillReturn("/api/products/1"))
@ -60,31 +72,21 @@
.BDDfy();
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
private void WhenICallTheMiddleware()
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(_downstreamUrlTemplateVariableReplacer.Object);
services.AddSingleton(ScopedRepository.Object);
services.AddSingleton(_urlBuilder.Object);
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseDownstreamUrlCreatorMiddleware();
_middleware = new DownstreamUrlCreatorMiddleware(_next, _loggerFactory.Object, _downstreamUrlTemplateVariableReplacer.Object, _urlBuilder.Object);
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
{
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
ScopedRepository
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
.Returns(_downstreamRoute);
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
}
private void GivenTheDownstreamRequestUriIs(string uri)
{
_downstreamRequest.RequestUri = new Uri(uri);
_downstreamContext.DownstreamRequest.RequestUri = new Uri(uri);
}
private void GivenTheUrlReplacerWillReturn(string path)
@ -97,7 +99,7 @@
private void ThenTheDownstreamRequestUriIs(string expectedUri)
{
_downstreamRequest.RequestUri.OriginalString.ShouldBe(expectedUri);
_downstreamContext.DownstreamRequest.RequestUri.OriginalString.ShouldBe(expectedUri);
}
}
}

View File

@ -29,6 +29,9 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
new DownstreamRoute(
new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
@ -43,7 +46,10 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
new DownstreamRoute(
new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("/")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("/")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
@ -56,7 +62,10 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
{
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("api")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("api")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
@ -69,7 +78,10 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
{
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("api/")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("api/")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
@ -82,7 +94,10 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
{
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("api/product/products/")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("api/product/products/")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
@ -100,7 +115,10 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables,
new ReRouteBuilder()
.WithDownstreamPathTemplate("productservice/products/{productId}/")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("productservice/products/{productId}/")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
@ -118,7 +136,10 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables,
new ReRouteBuilder()
.WithDownstreamPathTemplate("productservice/products/{productId}/variants")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("productservice/products/{productId}/variants")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
@ -137,7 +158,10 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables,
new ReRouteBuilder()
.WithDownstreamPathTemplate("productservice/products/{productId}/variants/{variantId}")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("productservice/products/{productId}/variants/{variantId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
@ -157,8 +181,11 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
this.Given(x => x.GivenThereIsAUrlMatch(new DownstreamRoute(templateVariables,
new ReRouteBuilder()
.WithDownstreamPathTemplate("productservice/category/{categoryId}/products/{productId}/variants/{variantId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("productservice/category/{categoryId}/products/{productId}/variants/{variantId}")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())))
.When(x => x.WhenIReplaceTheTemplateVariables())
.Then(x => x.ThenTheDownstreamUrlPathIsReturned("productservice/category/34/products/1/variants/12"))
@ -172,7 +199,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator.UrlTemplateReplacer
private void WhenIReplaceTheTemplateVariables()
{
_result = _downstreamPathReplacer.Replace(_downstreamRoute.ReRoute.DownstreamPathTemplate, _downstreamRoute.TemplatePlaceholderNameAndValues);
_result = _downstreamPathReplacer.Replace(_downstreamRoute.ReRoute.DownstreamReRoute[0].DownstreamPathTemplate, _downstreamRoute.TemplatePlaceholderNameAndValues);
}
private void ThenTheDownstreamUrlPathIsReturned(string expected)

View File

@ -1,10 +1,10 @@
using Ocelot.Middleware;
namespace Ocelot.UnitTests.Errors
{
using System;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.Errors.Middleware;
using Ocelot.Logging;
using Shouldly;
@ -14,18 +14,41 @@ namespace Ocelot.UnitTests.Errors
using Ocelot.Configuration.Provider;
using Moq;
using Ocelot.Configuration;
using Rafty.Concensus;
using Ocelot.Errors;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Infrastructure.RequestData;
public class ExceptionHandlerMiddlewareTests : ServerHostedMiddlewareTest
public class ExceptionHandlerMiddlewareTests
{
bool _shouldThrowAnException = false;
private Mock<IOcelotConfigurationProvider> _provider;
private Mock<IRequestScopedDataRepository> _repo;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger;
private ExceptionHandlerMiddleware _middleware;
private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
public ExceptionHandlerMiddlewareTests()
{
_provider = new Mock<IOcelotConfigurationProvider>();
GivenTheTestServerIsConfigured();
_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);
_next = async context => {
await Task.CompletedTask;
if (_shouldThrowAnException)
{
throw new Exception("BOOM");
}
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
};
_middleware = new ExceptionHandlerMiddleware(_next, _loggerFactory.Object, _provider.Object, _repo.Object);
}
[Fact]
@ -99,6 +122,17 @@ namespace Ocelot.UnitTests.Errors
.BDDfy();
}
private void WhenICallTheMiddlewareWithTheRequestIdKey(string key, string value)
{
_downstreamContext.HttpContext.Request.Headers.Add(key, value);
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void WhenICallTheMiddleware()
{
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void GivenTheConfigThrows()
{
var ex = new Exception("outer", new Exception("inner"));
@ -108,7 +142,7 @@ namespace Ocelot.UnitTests.Errors
private void ThenAnExceptionIsThrown()
{
ResponseMessage.StatusCode.ShouldBe(HttpStatusCode.InternalServerError);
_downstreamContext.HttpContext.Response.StatusCode.ShouldBe(500);
}
private void GivenTheConfigReturnsError()
@ -130,7 +164,7 @@ namespace Ocelot.UnitTests.Errors
private void TheRequestIdIsSet(string key, string value)
{
ScopedRepository.Verify(x => x.Add<string>(key, value), Times.Once);
_repo.Verify(x => x.Add<string>(key, value), Times.Once);
}
private void GivenTheConfigurationIs(IOcelotConfiguration config)
@ -140,31 +174,6 @@ namespace Ocelot.UnitTests.Errors
.Setup(x => x.Get()).ReturnsAsync(response);
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(ScopedRepository.Object);
services.AddSingleton<IOcelotConfigurationProvider>(_provider.Object);
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseExceptionHandlerMiddleware();
app.Run(DownstreamExceptionSimulator);
}
private async Task DownstreamExceptionSimulator(HttpContext context)
{
await Task.CompletedTask;
if (_shouldThrowAnException)
{
throw new Exception("BOOM");
}
context.Response.StatusCode = (int)HttpStatusCode.OK;
}
private void GivenAnExceptionWillNotBeThrownDownstream()
{
@ -178,17 +187,18 @@ namespace Ocelot.UnitTests.Errors
private void ThenTheResponseIsOk()
{
ResponseMessage.StatusCode.ShouldBe(HttpStatusCode.OK);
_downstreamContext.HttpContext.Response.StatusCode.ShouldBe(200);
}
private void ThenTheResponseIsError()
{
ResponseMessage.StatusCode.ShouldBe(HttpStatusCode.InternalServerError);
_downstreamContext.HttpContext.Response.StatusCode.ShouldBe(500);
}
private void TheRequestIdIsNotSet()
{
ScopedRepository.Verify(x => x.Add<string>(It.IsAny<string>(), It.IsAny<string>()), Times.Never);
_repo.Verify(x => x.Add<string>(It.IsAny<string>(), It.IsAny<string>()), Times.Never);
}
}
}
}

View File

@ -1,36 +1,43 @@
using Xunit;
using Shouldly;
using Ocelot.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using Ocelot.Headers.Middleware;
using TestStack.BDDfy;
using System.Linq;
using System.Threading.Tasks;
using System;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using Moq;
using Ocelot.Configuration;
using Ocelot.DownstreamRouteFinder;
using Ocelot.Responses;
using Ocelot.Configuration.Builder;
using Ocelot.Headers;
using System.Net.Http;
using Ocelot.Authorisation.Middleware;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Middleware;
namespace Ocelot.UnitTests.Headers
{
public class HttpHeadersTransformationMiddlewareTests : ServerHostedMiddlewareTest
public class HttpHeadersTransformationMiddlewareTests
{
private Mock<IHttpContextRequestHeaderReplacer> _preReplacer;
private Mock<IHttpResponseHeaderReplacer> _postReplacer;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger;
private HttpHeadersTransformationMiddleware _middleware;
private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
public HttpHeadersTransformationMiddlewareTests()
{
_preReplacer = new Mock<IHttpContextRequestHeaderReplacer>();
_postReplacer = new Mock<IHttpResponseHeaderReplacer>();
GivenTheTestServerIsConfigured();
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
_next = async context => {
//do nothing
};
_middleware = new HttpHeadersTransformationMiddleware(_next, _loggerFactory.Object, _preReplacer.Object, _postReplacer.Object);
}
[Fact]
@ -46,27 +53,34 @@ namespace Ocelot.UnitTests.Headers
.BDDfy();
}
private void WhenICallTheMiddleware()
{
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void GivenTheDownstreamRequestIs()
{
var request = new HttpRequestMessage();
var response = new OkResponse<HttpRequestMessage>(request);
ScopedRepository.Setup(x => x.Get<HttpRequestMessage>("DownstreamRequest")).Returns(response);
_downstreamContext.DownstreamRequest = new HttpRequestMessage();
}
private void GivenTheHttpResponseMessageIs()
{
var httpResponseMessage = new HttpResponseMessage();
var response = new OkResponse<HttpResponseMessage>(httpResponseMessage);
ScopedRepository.Setup(x => x.Get<HttpResponseMessage>("HttpResponseMessage")).Returns(response);
_downstreamContext.DownstreamResponse = new HttpResponseMessage();
}
private void GivenTheReRouteHasPreFindAndReplaceSetUp()
{
var fAndRs = new List<HeaderFindAndReplace>();
var reRoute = new ReRouteBuilder().WithUpstreamHeaderFindAndReplace(fAndRs).WithDownstreamHeaderFindAndReplace(fAndRs).Build();
var reRoute = new ReRouteBuilder()
.WithDownstreamReRoute(new DownstreamReRouteBuilder().WithUpstreamHeaderFindAndReplace(fAndRs)
.WithDownstreamHeaderFindAndReplace(fAndRs).Build())
.Build();
var dR = new DownstreamRoute(null, reRoute);
var response = new OkResponse<DownstreamRoute>(dR);
ScopedRepository.Setup(x => x.Get<DownstreamRoute>("DownstreamRoute")).Returns(response);
_downstreamContext.TemplatePlaceholderNameAndValues = dR.TemplatePlaceholderNameAndValues;
_downstreamContext.DownstreamReRoute = dR.ReRoute.DownstreamReRoute[0];
}
private void ThenTheIHttpContextRequestHeaderReplacerIsCalledCorrectly()
@ -81,21 +95,7 @@ namespace Ocelot.UnitTests.Headers
private void GivenTheFollowingRequest()
{
Client.DefaultRequestHeaders.Add("test", "test");
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(ScopedRepository.Object);
services.AddSingleton(_preReplacer.Object);
services.AddSingleton(_postReplacer.Object);
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseHttpHeadersTransformationMiddleware();
_downstreamContext.HttpContext.Request.Headers.Add("test", "test");
}
}
}
}

View File

@ -1,13 +1,17 @@
namespace Ocelot.UnitTests.Headers
using Ocelot.Middleware;
namespace Ocelot.UnitTests.Headers
{
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
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;
@ -16,22 +20,28 @@
using TestStack.BDDfy;
using Xunit;
public class HttpRequestHeadersBuilderMiddlewareTests : ServerHostedMiddlewareTest
public class HttpRequestHeadersBuilderMiddlewareTests
{
private readonly Mock<IAddHeadersToRequest> _addHeaders;
private readonly HttpRequestMessage _downstreamRequest;
private Response<DownstreamRoute> _downstreamRoute;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger;
private HttpRequestHeadersBuilderMiddleware _middleware;
private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
public HttpRequestHeadersBuilderMiddlewareTests()
{
_addHeaders = new Mock<IAddHeadersToRequest>();
_downstreamRequest = new HttpRequestMessage();
ScopedRepository
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
GivenTheTestServerIsConfigured();
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<HttpRequestHeadersBuilderMiddleware>()).Returns(_logger.Object);
_next = async context => {
//do nothing
};
_middleware = new HttpRequestHeadersBuilderMiddleware(_next, _loggerFactory.Object, _addHeaders.Object);
_downstreamContext.DownstreamRequest = new HttpRequestMessage();
}
[Fact]
@ -39,11 +49,14 @@
{
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithClaimsToHeaders(new List<ClaimToThing>
{
new ClaimToThing("UserId", "Subject", "", 0)
})
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithClaimsToHeaders(new List<ClaimToThing>
{
new ClaimToThing("UserId", "Subject", "", 0)
})
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
@ -54,25 +67,16 @@
.BDDfy();
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
private void WhenICallTheMiddleware()
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(_addHeaders.Object);
services.AddSingleton(ScopedRepository.Object);
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseHttpRequestHeadersBuilderMiddleware();
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
{
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
ScopedRepository
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
.Returns(_downstreamRoute);
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
}
private void GivenTheAddHeadersToDownstreamRequestReturnsOk()
@ -91,7 +95,7 @@
.Verify(x => x.SetHeadersOnDownstreamRequest(
It.IsAny<List<ClaimToThing>>(),
It.IsAny<IEnumerable<System.Security.Claims.Claim>>(),
_downstreamRequest), Times.Once);
_downstreamContext.DownstreamRequest), Times.Once);
}
}
}

View File

@ -12,7 +12,7 @@ namespace Ocelot.UnitTests.LoadBalancer
{
public class LoadBalancerFactoryTests
{
private ReRoute _reRoute;
private DownstreamReRoute _reRoute;
private LoadBalancerFactory _factory;
private ILoadBalancer _result;
private Mock<IServiceDiscoveryProviderFactory> _serviceProviderFactory;
@ -29,7 +29,7 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact]
public void should_return_no_load_balancer()
{
var reRoute = new ReRouteBuilder()
var reRoute = new DownstreamReRouteBuilder()
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build();
@ -44,9 +44,9 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact]
public void should_return_round_robin_load_balancer()
{
var reRoute = new ReRouteBuilder()
var reRoute = new DownstreamReRouteBuilder()
.WithLoadBalancer("RoundRobin")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamHttpMethod(new List<string> {"Get"})
.Build();
this.Given(x => x.GivenAReRoute(reRoute))
@ -60,9 +60,9 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact]
public void should_return_round_least_connection_balancer()
{
var reRoute = new ReRouteBuilder()
var reRoute = new DownstreamReRouteBuilder()
.WithLoadBalancer("LeastConnection")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamHttpMethod(new List<string> {"Get"})
.Build();
this.Given(x => x.GivenAReRoute(reRoute))
@ -76,9 +76,9 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact]
public void should_call_service_provider()
{
var reRoute = new ReRouteBuilder()
var reRoute = new DownstreamReRouteBuilder()
.WithLoadBalancer("RoundRobin")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithUpstreamHttpMethod(new List<string> {"Get"})
.Build();
this.Given(x => x.GivenAReRoute(reRoute))
@ -97,17 +97,17 @@ namespace Ocelot.UnitTests.LoadBalancer
private void GivenTheServiceProviderFactoryReturns()
{
_serviceProviderFactory
.Setup(x => x.Get(It.IsAny<ServiceProviderConfiguration>(), It.IsAny<ReRoute>()))
.Setup(x => x.Get(It.IsAny<ServiceProviderConfiguration>(), It.IsAny<DownstreamReRoute>()))
.Returns(_serviceProvider.Object);
}
private void ThenTheServiceProviderIsCalledCorrectly()
{
_serviceProviderFactory
.Verify(x => x.Get(It.IsAny<ServiceProviderConfiguration>(), It.IsAny<ReRoute>()), Times.Once);
.Verify(x => x.Get(It.IsAny<ServiceProviderConfiguration>(), It.IsAny<DownstreamReRoute>()), Times.Once);
}
private void GivenAReRoute(ReRoute reRoute)
private void GivenAReRoute(DownstreamReRoute reRoute)
{
_reRoute = reRoute;
}
@ -122,4 +122,4 @@ namespace Ocelot.UnitTests.LoadBalancer
_result.ShouldBeOfType<T>();
}
}
}
}

View File

@ -14,13 +14,13 @@ namespace Ocelot.UnitTests.LoadBalancer
{
public class LoadBalancerHouseTests
{
private ReRoute _reRoute;
private DownstreamReRoute _reRoute;
private ILoadBalancer _loadBalancer;
private readonly LoadBalancerHouse _loadBalancerHouse;
private Response _addResult;
private Response<ILoadBalancer> _getResult;
private string _key;
private Mock<ILoadBalancerFactory> _factory;
private readonly Mock<ILoadBalancerFactory> _factory;
private ServiceProviderConfiguration _serviceProviderConfig;
public LoadBalancerHouseTests()
@ -32,7 +32,7 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact]
public void should_store_load_balancer_on_first_request()
{
var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build();
var reRoute = new DownstreamReRouteBuilder().WithReRouteKey("test").Build();
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
.Then(x => x.ThenItIsAdded())
@ -42,7 +42,7 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact]
public void should_not_store_load_balancer_on_second_request()
{
var reRoute = new ReRouteBuilder().WithLoadBalancer("FakeLoadBalancer").WithReRouteKey("test").Build();
var reRoute = new DownstreamReRouteBuilder().WithLoadBalancer("FakeLoadBalancer").WithReRouteKey("test").Build();
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
@ -53,8 +53,8 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact]
public void should_store_load_balancers_by_key()
{
var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build();
var reRouteTwo = new ReRouteBuilder().WithReRouteKey("testtwo").Build();
var reRoute = new DownstreamReRouteBuilder().WithLoadBalancer("FakeLoadBalancer").WithReRouteKey("test").Build();
var reRouteTwo = new DownstreamReRouteBuilder().WithLoadBalancer("FakeRoundRobinLoadBalancer").WithReRouteKey("testtwo").Build();
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
.And(x => x.GivenThereIsALoadBalancer(reRouteTwo, new FakeRoundRobinLoadBalancer()))
@ -68,7 +68,7 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact]
public void should_return_error_if_exception()
{
var reRoute = new ReRouteBuilder().Build();
var reRoute = new DownstreamReRouteBuilder().Build();
this.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
.Then(x => x.ThenAnErrorIsReturned())
@ -78,9 +78,9 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact]
public void should_get_new_load_balancer_if_reroute_load_balancer_has_changed()
{
var reRoute = new ReRouteBuilder().WithLoadBalancer("FakeLoadBalancer").WithReRouteKey("test").Build();
var reRoute = new DownstreamReRouteBuilder().WithLoadBalancer("FakeLoadBalancer").WithReRouteKey("test").Build();
var reRouteTwo = new ReRouteBuilder().WithLoadBalancer("LeastConnection").WithReRouteKey("test").Build();
var reRouteTwo = new DownstreamReRouteBuilder().WithLoadBalancer("LeastConnection").WithReRouteKey("test").Build();
this.Given(x => x.GivenThereIsALoadBalancer(reRoute, new FakeLoadBalancer()))
.When(x => x.WhenWeGetTheLoadBalancer(reRoute))
@ -90,7 +90,7 @@ namespace Ocelot.UnitTests.LoadBalancer
.BDDfy();
}
private void WhenIGetTheReRouteWithTheSameKeyButDifferentLoadBalancer(ReRoute reRoute)
private void WhenIGetTheReRouteWithTheSameKeyButDifferentLoadBalancer(DownstreamReRoute reRoute)
{
_reRoute = reRoute;
_factory.Setup(x => x.Get(_reRoute, _serviceProviderConfig)).ReturnsAsync(new LeastConnection(null, null));
@ -117,7 +117,7 @@ namespace Ocelot.UnitTests.LoadBalancer
}
private void GivenThereIsALoadBalancer(ReRoute reRoute, ILoadBalancer loadBalancer)
private void GivenThereIsALoadBalancer(DownstreamReRoute reRoute, ILoadBalancer loadBalancer)
{
_reRoute = reRoute;
_loadBalancer = loadBalancer;
@ -125,7 +125,7 @@ namespace Ocelot.UnitTests.LoadBalancer
_getResult = _loadBalancerHouse.Get(reRoute, _serviceProviderConfig).Result;
}
private void WhenWeGetTheLoadBalancer(ReRoute reRoute)
private void WhenWeGetTheLoadBalancer(DownstreamReRoute reRoute)
{
_getResult = _loadBalancerHouse.Get(reRoute, _serviceProviderConfig).Result;
}

View File

@ -1,14 +1,18 @@
using Ocelot.Middleware;
namespace Ocelot.UnitTests.LoadBalancer
{
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Configuration.Provider;
using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Errors;
using Ocelot.LoadBalancer.LoadBalancers;
using Ocelot.LoadBalancer.Middleware;
@ -19,7 +23,7 @@ namespace Ocelot.UnitTests.LoadBalancer
using TestStack.BDDfy;
using Xunit;
public class LoadBalancerMiddlewareTests : ServerHostedMiddlewareTest
public class LoadBalancerMiddlewareTests
{
private readonly Mock<ILoadBalancerHouse> _loadBalancerHouse;
private readonly Mock<ILoadBalancer> _loadBalancer;
@ -29,6 +33,11 @@ namespace Ocelot.UnitTests.LoadBalancer
private ErrorResponse<ServiceHostAndPort> _getHostAndPortError;
private HttpRequestMessage _downstreamRequest;
private ServiceProviderConfiguration _config;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger;
private LoadBalancingMiddleware _middleware;
private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
public LoadBalancerMiddlewareTests()
{
@ -36,28 +45,29 @@ namespace Ocelot.UnitTests.LoadBalancer
_loadBalancer = new Mock<ILoadBalancer>();
_loadBalancerHouse = new Mock<ILoadBalancerHouse>();
_downstreamRequest = new HttpRequestMessage(HttpMethod.Get, "");
ScopedRepository
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
GivenTheTestServerIsConfigured();
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<LoadBalancingMiddleware>()).Returns(_logger.Object);
_next = async context => {
//do nothing
};
_downstreamContext.DownstreamRequest = _downstreamRequest;
}
[Fact]
public void should_call_scoped_data_repository_correctly()
{
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
new ReRouteBuilder()
var downstreamRoute = new DownstreamReRouteBuilder()
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
.Build();
var serviceProviderConfig = new ServiceProviderConfigurationBuilder()
.Build();
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))
.And(x => GivenTheConfigurationIs(serviceProviderConfig))
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute, new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>()))
.And(x => x.GivenTheLoadBalancerHouseReturns())
.And(x => x.GivenTheLoadBalancerReturns())
.When(x => x.WhenICallTheMiddleware())
@ -68,17 +78,16 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact]
public void should_set_pipeline_error_if_cannot_get_load_balancer()
{
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
new ReRouteBuilder()
var downstreamRoute = new DownstreamReRouteBuilder()
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
.Build();
var serviceProviderConfig = new ServiceProviderConfigurationBuilder()
.Build();
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))
.And(x => GivenTheConfigurationIs(serviceProviderConfig))
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute, new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>()))
.And(x => x.GivenTheLoadBalancerHouseReturnsAnError())
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline())
@ -88,17 +97,16 @@ namespace Ocelot.UnitTests.LoadBalancer
[Fact]
public void should_set_pipeline_error_if_cannot_get_least()
{
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
new ReRouteBuilder()
var downstreamRoute = new DownstreamReRouteBuilder()
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
.Build();
var serviceProviderConfig = new ServiceProviderConfigurationBuilder()
.Build();
this.Given(x => x.GivenTheDownStreamUrlIs("http://my.url/abc?q=123"))
.And(x => GivenTheConfigurationIs(serviceProviderConfig))
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute, new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>()))
.And(x => x.GivenTheLoadBalancerHouseReturns())
.And(x => x.GivenTheLoadBalancerReturnsAnError())
.When(x => x.WhenICallTheMiddleware())
@ -106,24 +114,16 @@ namespace Ocelot.UnitTests.LoadBalancer
.BDDfy();
}
private void WhenICallTheMiddleware()
{
_middleware = new LoadBalancingMiddleware(_next, _loggerFactory.Object, _loadBalancerHouse.Object);
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void GivenTheConfigurationIs(ServiceProviderConfiguration config)
{
_config = config;
ScopedRepository
.Setup(x => x.Get<ServiceProviderConfiguration>("ServiceProviderConfiguration")).Returns(new OkResponse<ServiceProviderConfiguration>(config));
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(_loadBalancerHouse.Object);
services.AddSingleton(ScopedRepository.Object);
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseLoadBalancingMiddleware();
_downstreamContext.ServiceProviderConfiguration = config;
}
private void GivenTheDownStreamUrlIs(string downstreamUrl)
@ -147,18 +147,16 @@ namespace Ocelot.UnitTests.LoadBalancer
.ReturnsAsync(new OkResponse<ServiceHostAndPort>(_hostAndPort));
}
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
private void GivenTheDownStreamRouteIs(DownstreamReRoute downstreamRoute, List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue> placeholder)
{
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
ScopedRepository
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
.Returns(_downstreamRoute);
_downstreamContext.TemplatePlaceholderNameAndValues = placeholder;
_downstreamContext.DownstreamReRoute = downstreamRoute;
}
private void GivenTheLoadBalancerHouseReturns()
{
_loadBalancerHouse
.Setup(x => x.Get(It.IsAny<ReRoute>(), It.IsAny<ServiceProviderConfiguration>()))
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>(), It.IsAny<ServiceProviderConfiguration>()))
.ReturnsAsync(new OkResponse<ILoadBalancer>(_loadBalancer.Object));
}
@ -170,40 +168,32 @@ namespace Ocelot.UnitTests.LoadBalancer
});
_loadBalancerHouse
.Setup(x => x.Get(It.IsAny<ReRoute>(), It.IsAny<ServiceProviderConfiguration>()))
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>(), It.IsAny<ServiceProviderConfiguration>()))
.ReturnsAsync(_getLoadBalancerHouseError);
}
private void ThenAnErrorStatingLoadBalancerCouldNotBeFoundIsSetOnPipeline()
{
ScopedRepository
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
ScopedRepository
.Verify(x => x.Add("OcelotMiddlewareErrors", _getLoadBalancerHouseError.Errors), Times.Once);
_downstreamContext.IsError.ShouldBeTrue();
_downstreamContext.Errors.ShouldBe(_getLoadBalancerHouseError.Errors);
}
private void ThenAnErrorSayingReleaseFailedIsSetOnThePipeline()
{
ScopedRepository
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
ScopedRepository
.Verify(x => x.Add("OcelotMiddlewareErrors", It.IsAny<List<Error>>()), Times.Once);
_downstreamContext.IsError.ShouldBeTrue();
_downstreamContext.Errors.ShouldBe(It.IsAny<List<Error>>());
}
private void ThenAnErrorStatingHostAndPortCouldNotBeFoundIsSetOnPipeline()
{
ScopedRepository
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once);
_downstreamContext.IsError.ShouldBeTrue();
_downstreamContext.Errors.ShouldBe(_getHostAndPortError.Errors);
ScopedRepository
.Verify(x => x.Add("OcelotMiddlewareErrors", _getHostAndPortError.Errors), Times.Once);
}
private void ThenTheDownstreamUrlIsReplacedWith(string expectedUri)
{
_downstreamRequest.RequestUri.OriginalString.ShouldBe(expectedUri);
_downstreamContext.DownstreamRequest.RequestUri.OriginalString.ShouldBe(expectedUri);
}
}
}

View File

@ -0,0 +1,69 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer;
using Shouldly;
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;
public MultiplexerTests()
{
_aggregator = new Mock<IResponseAggregator>();
_context = new DownstreamContext(new DefaultHttpContext());
_pipeline = async context => { _count++; };
_multiplexer = new Multiplexer(_aggregator.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);
}
}
}

View File

@ -0,0 +1,87 @@
namespace Ocelot.UnitTests.Middleware
{
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Internal;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using Ocelot.Middleware.Pipeline;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
public class OcelotPiplineBuilderTests
{
private readonly IServiceCollection _services;
private IServiceProvider _serviceProvider;
private readonly IConfiguration _configRoot;
private IOcelotBuilder _ocelotBuilder;
private DownstreamContext _downstreamContext;
private int _counter;
public OcelotPiplineBuilderTests()
{
_configRoot = new ConfigurationRoot(new List<IConfigurationProvider>());
_services = new ServiceCollection();
_services.AddSingleton<IHostingEnvironment, HostingEnvironment>();
_services.AddSingleton<IConfiguration>(_configRoot);
_services.AddOcelot();
}
[Fact]
public void should_build_generic()
{
this.When(x => WhenIUseAGeneric())
.Then(x => ThenTheGenericIsInThePipeline())
.BDDfy();
}
[Fact]
public void should_build_func()
{
this.When(x => WhenIUseAFunc())
.Then(x => ThenTheFuncIsInThePipeline())
.BDDfy();
}
private void WhenIUseAGeneric()
{
var provider = _services.BuildServiceProvider();
IOcelotPipelineBuilder builder = new OcelotPipelineBuilder(provider);
builder = builder.UseMiddleware<Ocelot.Errors.Middleware.ExceptionHandlerMiddleware>();
var del = builder.Build();
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
del.Invoke(_downstreamContext);
}
private void ThenTheGenericIsInThePipeline()
{
_downstreamContext.HttpContext.Response.StatusCode.ShouldBe(500);
}
private void WhenIUseAFunc()
{
_counter = 0;
var provider = _services.BuildServiceProvider();
IOcelotPipelineBuilder builder = new OcelotPipelineBuilder(provider);
builder = builder.Use(async (ctx, next) =>
{
_counter++;
await next.Invoke();
});
var del = builder.Build();
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
del.Invoke(_downstreamContext);
}
private void ThenTheFuncIsInThePipeline()
{
_counter.ShouldBe(1);
_downstreamContext.HttpContext.Response.StatusCode.ShouldBe(404);
}
}
}

View File

@ -0,0 +1,202 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Text;
using Microsoft.AspNetCore.Http;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Errors;
using Ocelot.Middleware;
using Ocelot.Middleware.Multiplexer;
using Ocelot.UnitTests.Responder;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
namespace Ocelot.UnitTests.Middleware
{
public class SimpleJsonResponseAggregatorTests
{
private readonly SimpleJsonResponseAggregator _aggregator;
private List<DownstreamContext> _downstreamContexts;
private DownstreamContext _upstreamContext;
private ReRoute _reRoute;
public SimpleJsonResponseAggregatorTests()
{
_aggregator = new SimpleJsonResponseAggregator();
}
[Fact]
public void should_map_all_downstream_to_upstream_when_not_aggregate()
{
var billDownstreamReRoute = new DownstreamReRouteBuilder().WithKey("Bill").Build();
var downstreamReRoutes = new List<DownstreamReRoute>
{
billDownstreamReRoute,
};
var reRoute = new ReRouteBuilder()
.WithDownstreamReRoutes(downstreamReRoutes)
.Build();
var billDownstreamContext = new DownstreamContext(new DefaultHttpContext())
{
DownstreamResponse =
new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("Bill says hi") },
DownstreamReRoute = billDownstreamReRoute,
Errors = new List<Error> { new AnyError() },
DownstreamRequest = new HttpRequestMessage(HttpMethod.Get, new Uri("http://www.bbc.co.uk")),
};
var downstreamContexts = new List<DownstreamContext> { billDownstreamContext };
this.Given(x => GivenTheUpstreamContext(new DownstreamContext(new DefaultHttpContext())))
.And(x => GivenTheReRoute(reRoute))
.And(x => GivenTheDownstreamContext(downstreamContexts))
.When(x => WhenIAggregate())
.Then(x => ThenTheContentIs("Bill says hi"))
.And(x => ThenTheUpstreamContextIsMappedForNonAggregate())
.BDDfy();
}
[Fact]
public void should_aggregate_n_responses_and_set_response_content_on_upstream_context()
{
var billDownstreamReRoute = new DownstreamReRouteBuilder().WithKey("Bill").Build();
var georgeDownstreamReRoute = new DownstreamReRouteBuilder().WithKey("George").Build();
var downstreamReRoutes = new List<DownstreamReRoute>
{
billDownstreamReRoute,
georgeDownstreamReRoute
};
var reRoute = new ReRouteBuilder()
.WithDownstreamReRoutes(downstreamReRoutes)
.Build();
var billDownstreamContext = new DownstreamContext(new DefaultHttpContext())
{
DownstreamResponse =
new HttpResponseMessage(HttpStatusCode.OK) {Content = new StringContent("Bill says hi")},
DownstreamReRoute = billDownstreamReRoute
};
var georgeDownstreamContext = new DownstreamContext(new DefaultHttpContext())
{
DownstreamResponse =
new HttpResponseMessage(HttpStatusCode.OK) {Content = new StringContent("George says hi")},
DownstreamReRoute = georgeDownstreamReRoute
};
var downstreamContexts = new List<DownstreamContext> { billDownstreamContext, georgeDownstreamContext };
var expected = "{\"Bill\":Bill says hi,\"George\":George says hi}";
this.Given(x => GivenTheUpstreamContext(new DownstreamContext(new DefaultHttpContext())))
.And(x => GivenTheReRoute(reRoute))
.And(x => GivenTheDownstreamContext(downstreamContexts))
.When(x => WhenIAggregate())
.Then(x => ThenTheContentIs(expected))
.And(x => ThenTheContentTypeIs("application/json"))
.BDDfy();
}
[Fact]
public void should_return_error_if_any_downstreams_have_errored()
{
var billDownstreamReRoute = new DownstreamReRouteBuilder().WithKey("Bill").Build();
var georgeDownstreamReRoute = new DownstreamReRouteBuilder().WithKey("George").Build();
var downstreamReRoutes = new List<DownstreamReRoute>
{
billDownstreamReRoute,
georgeDownstreamReRoute
};
var reRoute = new ReRouteBuilder()
.WithDownstreamReRoutes(downstreamReRoutes)
.Build();
var billDownstreamContext = new DownstreamContext(new DefaultHttpContext())
{
DownstreamResponse =
new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("Bill says hi") },
DownstreamReRoute = billDownstreamReRoute
};
var georgeDownstreamContext = new DownstreamContext(new DefaultHttpContext())
{
DownstreamResponse =
new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("Error") },
DownstreamReRoute = georgeDownstreamReRoute,
Errors = new List<Error>() { new AnyError() }
};
var downstreamContexts = new List<DownstreamContext> { billDownstreamContext, georgeDownstreamContext };
var expected = "Error";
this.Given(x => GivenTheUpstreamContext(new DownstreamContext(new DefaultHttpContext())))
.And(x => GivenTheReRoute(reRoute))
.And(x => GivenTheDownstreamContext(downstreamContexts))
.When(x => WhenIAggregate())
.Then(x => ThenTheContentIs(expected))
.And(x => ThenTheErrorIsMapped())
.BDDfy();
}
private void ThenTheErrorIsMapped()
{
_upstreamContext.Errors.ShouldBe(_downstreamContexts[1].Errors);
_upstreamContext.DownstreamResponse.ShouldBe(_downstreamContexts[1].DownstreamResponse);
}
private void GivenTheReRoute(ReRoute reRoute)
{
_reRoute = reRoute;
}
private void GivenTheUpstreamContext(DownstreamContext upstreamContext)
{
_upstreamContext = upstreamContext;
}
private void GivenTheDownstreamContext(List<DownstreamContext> downstreamContexts)
{
_downstreamContexts = downstreamContexts;
}
private void WhenIAggregate()
{
_aggregator.Aggregate(_reRoute, _upstreamContext, _downstreamContexts).GetAwaiter().GetResult();
}
private void ThenTheContentIs(string expected)
{
var content = _upstreamContext.DownstreamResponse.Content.ReadAsStringAsync()
.GetAwaiter()
.GetResult();
content.ShouldBe(expected);
}
private void ThenTheContentTypeIs(string expected)
{
_upstreamContext.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);
}
}
}

View File

@ -1,4 +1,6 @@
namespace Ocelot.UnitTests.QueryStrings
using Ocelot.Middleware;
namespace Ocelot.UnitTests.QueryStrings
{
using System.Collections.Generic;
using System.Net.Http;
@ -16,22 +18,30 @@
using Xunit;
using System.Security.Claims;
using Microsoft.AspNetCore.Builder;
using Ocelot.DownstreamRouteFinder.Middleware;
using Microsoft.AspNetCore.Http;
public class QueryStringBuilderMiddlewareTests : ServerHostedMiddlewareTest
public class QueryStringBuilderMiddlewareTests
{
private readonly Mock<IAddQueriesToRequest> _addQueries;
private readonly HttpRequestMessage _downstreamRequest;
private Response<DownstreamRoute> _downstreamRoute;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger;
private QueryStringBuilderMiddleware _middleware;
private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
public QueryStringBuilderMiddlewareTests()
{
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<QueryStringBuilderMiddleware>()).Returns(_logger.Object);
_next = async context => {
//do nothing
};
_addQueries = new Mock<IAddQueriesToRequest>();
_downstreamRequest = new HttpRequestMessage();
ScopedRepository.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
GivenTheTestServerIsConfigured();
_downstreamContext.DownstreamRequest = new HttpRequestMessage();
_middleware = new QueryStringBuilderMiddleware(_next, _loggerFactory.Object, _addQueries.Object);
}
[Fact]
@ -39,11 +49,14 @@
{
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithClaimsToQueries(new List<ClaimToThing>
{
new ClaimToThing("UserId", "Subject", "", 0)
})
.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());
@ -54,17 +67,9 @@
.BDDfy();
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
private void WhenICallTheMiddleware()
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(_addQueries.Object);
services.AddSingleton(ScopedRepository.Object);
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseQueryStringBuilderMiddleware();
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void GivenTheAddHeadersToRequestReturnsOk()
@ -83,15 +88,13 @@
.Verify(x => x.SetQueriesOnDownstreamRequest(
It.IsAny<List<ClaimToThing>>(),
It.IsAny<IEnumerable<Claim>>(),
_downstreamRequest), Times.Once);
_downstreamContext.DownstreamRequest), Times.Once);
}
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
{
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
ScopedRepository
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
.Returns(_downstreamRoute);
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
}
}
}

View File

@ -1,11 +1,10 @@
namespace Ocelot.UnitTests.RateLimit
using Ocelot.Middleware;
namespace Ocelot.UnitTests.RateLimit
{
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
@ -13,27 +12,51 @@
using Ocelot.Logging;
using Ocelot.RateLimit;
using Ocelot.RateLimit.Middleware;
using Ocelot.Responses;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
using Ocelot.DownstreamRouteFinder.Middleware;
using Microsoft.Extensions.Caching.Memory;
using System.IO;
public class ClientRateLimitMiddlewareTests : ServerHostedMiddlewareTest
public class ClientRateLimitMiddlewareTests
{
private OkResponse<DownstreamRoute> _downstreamRoute;
private int responseStatusCode;
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()
{
GivenTheTestServerIsConfigured();
_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 = async (context) => {
};
_middleware = new ClientRateLimitMiddleware(_next, _loggerFactory.Object, _rateLimitCounterHandler);
}
[Fact]
public void should_call_middleware_and_ratelimiting()
{
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>(), false, "", "", new Ocelot.Configuration.RateLimitRule("1s", 100, 3), 429))
new ReRouteBuilder()
.WithDownstreamReRoute(new DownstreamReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
new RateLimitOptions(true, "ClientId", new List<string>(), false, "", "", new RateLimitRule("1s", 100, 3), 429))
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
@ -49,8 +72,13 @@
public void should_call_middleware_withWhitelistClient()
{
var downstreamRoute = new DownstreamRoute(new List<Ocelot.DownstreamRouteFinder.UrlMatcher.PlaceholderNameAndValue>(),
new ReRouteBuilder().WithEnableRateLimiting(true).WithRateLimitOptions(
new Ocelot.Configuration.RateLimitOptions(true, "ClientId", new List<string>() { "ocelotclient2" }, false, "", "", new RateLimitRule( "1s", 100,3),429))
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());
@ -60,31 +88,10 @@
.BDDfy();
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddMemoryCache();
services.AddSingleton<IRateLimitCounterHandler, MemoryCacheRateLimitCounterHandler>();
services.AddSingleton(ScopedRepository.Object);
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseRateLimiting();
app.Run(async context =>
{
context.Response.StatusCode = 200;
await context.Response.WriteAsync("This is ratelimit test");
});
}
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
{
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
ScopedRepository
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
.Returns(_downstreamRoute);
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
}
private void WhenICallTheMiddlewareMultipleTime(int times)
@ -93,11 +100,12 @@
for (int i = 0; i < times; i++)
{
var request = new HttpRequestMessage(new HttpMethod("GET"), Url);
var request = new HttpRequestMessage(new HttpMethod("GET"), _url);
request.Headers.Add("ClientId", clientId);
_downstreamContext.DownstreamRequest = request;
var response = Client.SendAsync(request);
responseStatusCode = (int)response.Result.StatusCode;
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
_responseStatusCode = (int)_downstreamContext.HttpContext.Response.StatusCode;
}
}
@ -107,22 +115,58 @@
for (int i = 0; i < 10; i++)
{
var request = new HttpRequestMessage(new HttpMethod("GET"), Url);
var request = new HttpRequestMessage(new HttpMethod("GET"), _url);
request.Headers.Add("ClientId", clientId);
_downstreamContext.DownstreamRequest = request;
_downstreamContext.HttpContext.Request.Headers.TryAdd("ClientId", clientId);
var response = Client.SendAsync(request);
responseStatusCode = (int)response.Result.StatusCode;
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
_responseStatusCode = (int)_downstreamContext.HttpContext.Response.StatusCode;
}
}
private void ThenresponseStatusCodeIs429()
{
responseStatusCode.ShouldBe(429);
_responseStatusCode.ShouldBe(429);
}
private void ThenresponseStatusCodeIs200()
{
responseStatusCode.ShouldBe(200);
_responseStatusCode.ShouldBe(200);
}
}
class FakeStream : Stream
{
public override void Flush()
{
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; }
}
}

View File

@ -1,4 +1,6 @@
namespace Ocelot.UnitTests.Request
using Ocelot.Middleware;
namespace Ocelot.UnitTests.Request
{
using System.Net.Http;
using Microsoft.AspNetCore.Http;
@ -10,6 +12,8 @@
using TestStack.BDDfy;
using Xunit;
using Ocelot.Responses;
using Ocelot.DownstreamRouteFinder.Middleware;
using Shouldly;
public class DownstreamRequestInitialiserMiddlewareTests
{
@ -19,17 +23,16 @@
readonly Mock<HttpRequest> _httpRequest;
readonly Mock<RequestDelegate> _next;
readonly Mock<OcelotRequestDelegate> _next;
readonly Mock<IRequestMapper> _requestMapper;
readonly Mock<IRequestScopedDataRepository> _repo;
readonly Mock<IOcelotLoggerFactory> _loggerFactory;
readonly Mock<IOcelotLogger> _logger;
Response<HttpRequestMessage> _mappedRequest;
private DownstreamContext _downstreamContext;
public DownstreamRequestInitialiserMiddlewareTests()
{
@ -37,8 +40,7 @@
_httpContext = new Mock<HttpContext>();
_httpRequest = new Mock<HttpRequest>();
_requestMapper = new Mock<IRequestMapper>();
_repo = new Mock<IRequestScopedDataRepository>();
_next = new Mock<RequestDelegate>();
_next = new Mock<OcelotRequestDelegate>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory = new Mock<IOcelotLoggerFactory>();
@ -49,8 +51,9 @@
_middleware = new DownstreamRequestInitialiserMiddleware(
_next.Object,
_loggerFactory.Object,
_repo.Object,
_requestMapper.Object);
_downstreamContext = new DownstreamContext(_httpContext.Object);
}
[Fact]
@ -104,7 +107,7 @@
private void WhenTheMiddlewareIsInvoked()
{
_middleware.Invoke(_httpContext.Object).GetAwaiter().GetResult();
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void ThenTheContexRequestIsMappedToADownstreamRequest()
@ -114,29 +117,28 @@
private void ThenTheDownstreamRequestIsStored()
{
_repo.Verify(r => r.Add("DownstreamRequest", _mappedRequest.Data), Times.Once);
_downstreamContext.DownstreamRequest.ShouldNotBeNull();
}
private void ThenTheDownstreamRequestIsNotStored()
{
_repo.Verify(r => r.Add("DownstreamRequest", It.IsAny<HttpRequestMessage>()), Times.Never);
_downstreamContext.DownstreamRequest.ShouldBeNull();
}
private void ThenAPipelineErrorIsStored()
{
_repo.Verify(r => r.Add("OcelotMiddlewareError", true), Times.Once);
_repo.Verify(r => r.Add("OcelotMiddlewareErrors", _mappedRequest.Errors), Times.Once);
_downstreamContext.IsError.ShouldBeTrue();
_downstreamContext.Errors.ShouldBe(_mappedRequest.Errors);
}
private void ThenTheNextMiddlewareIsInvoked()
{
_next.Verify(n => n(_httpContext.Object), Times.Once);
_next.Verify(n => n(_downstreamContext), Times.Once);
}
private void ThenTheNextMiddlewareIsNotInvoked()
{
_next.Verify(n => n(It.IsAny<HttpContext>()), Times.Never);
_next.Verify(n => n(It.IsAny<DownstreamContext>()), Times.Never);
}
}
}

View File

@ -1,152 +0,0 @@
namespace Ocelot.UnitTests.Request
{
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder;
using Ocelot.DownstreamRouteFinder.UrlMatcher;
using Ocelot.Infrastructure.RequestData;
using Ocelot.Logging;
using Ocelot.Request.Builder;
using Ocelot.Request.Middleware;
using Ocelot.Responses;
using TestStack.BDDfy;
using Xunit;
using Ocelot.Requester.QoS;
using Ocelot.Configuration;
using Microsoft.AspNetCore.Builder;
using Ocelot.Errors;
public class HttpRequestBuilderMiddlewareTests : ServerHostedMiddlewareTest
{
private readonly Mock<IRequestCreator> _requestBuilder;
private readonly Mock<IRequestScopedDataRepository> _scopedRepository;
private readonly Mock<IQosProviderHouse> _qosProviderHouse;
private readonly HttpRequestMessage _downstreamRequest;
private OkResponse<Ocelot.Request.Request> _request;
private OkResponse<string> _downstreamUrl;
private OkResponse<DownstreamRoute> _downstreamRoute;
public HttpRequestBuilderMiddlewareTests()
{
_qosProviderHouse = new Mock<IQosProviderHouse>();
_requestBuilder = new Mock<IRequestCreator>();
_scopedRepository = new Mock<IRequestScopedDataRepository>();
_downstreamRequest = new HttpRequestMessage();
_scopedRepository
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
GivenTheTestServerIsConfigured();
}
[Fact]
public void should_call_scoped_data_repository_correctly()
{
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithRequestIdKey("LSRequestId")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true,false))
.Build());
this.Given(x => x.GivenTheDownStreamUrlIs("any old string"))
.And(x => x.GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(new NoQoSProvider())))
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => x.GivenTheRequestBuilderReturns(new Ocelot.Request.Request(new HttpRequestMessage(), true, new NoQoSProvider(), false, false, "", false)))
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheScopedDataRepositoryIsCalledCorrectly())
.BDDfy();
}
[Fact]
public void should_call_scoped_data_repository_QosProviderError()
{
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithRequestIdKey("LSRequestId")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, true))
.Build());
this.Given(x => x.GivenTheDownStreamUrlIs("any old string"))
.And(x => x.GivenTheQosProviderHouseReturns(new ErrorResponse<IQoSProvider>(It.IsAny<Error>())))
.And(x => x.GivenTheDownStreamRouteIs(downstreamRoute))
.And(x => x.GivenTheRequestBuilderReturns(new Ocelot.Request.Request(new HttpRequestMessage(), true, new NoQoSProvider(), false, false, "", false)))
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheScopedDataRepositoryQosProviderError())
.BDDfy();
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(_qosProviderHouse.Object);
services.AddSingleton(_requestBuilder.Object);
services.AddSingleton(_scopedRepository.Object);
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseHttpRequestBuilderMiddleware();
}
private void GivenTheDownStreamUrlIs(string downstreamUrl)
{
_downstreamUrl = new OkResponse<string>(downstreamUrl);
_scopedRepository
.Setup(x => x.Get<string>(It.IsAny<string>()))
.Returns(_downstreamUrl);
}
private void GivenTheQosProviderHouseReturns(Response<IQoSProvider> qosProvider)
{
_qosProviderHouse
.Setup(x => x.Get(It.IsAny<ReRoute>()))
.Returns(qosProvider);
}
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
{
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
_scopedRepository
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
.Returns(_downstreamRoute);
}
private void GivenTheRequestBuilderReturns(Ocelot.Request.Request request)
{
_request = new OkResponse<Ocelot.Request.Request>(request);
_requestBuilder
.Setup(x => x.Build(It.IsAny<HttpRequestMessage>(),
It.IsAny<bool>(),
It.IsAny<IQoSProvider>(),
It.IsAny<bool>(),
It.IsAny<bool>(),
It.IsAny<string>(),
It.IsAny<bool>()))
.ReturnsAsync(_request);
}
private void ThenTheScopedDataRepositoryIsCalledCorrectly()
{
_scopedRepository
.Verify(x => x.Add("Request", _request.Data), Times.Once());
}
private void ThenTheScopedDataRepositoryQosProviderError()
{
_scopedRepository
.Verify(x => x.Add("OcelotMiddlewareError", true), Times.Once());
}
}
}

View File

@ -1,86 +0,0 @@
namespace Ocelot.UnitTests.Request
{
using System.Net.Http;
using Ocelot.Request.Builder;
using Ocelot.Requester.QoS;
using Ocelot.Responses;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
public class HttpRequestCreatorTests
{
private readonly IRequestCreator _requestCreator;
private readonly bool _isQos;
private readonly IQoSProvider _qoSProvider;
private readonly HttpRequestMessage _requestMessage;
private readonly bool _useCookieContainer;
private readonly bool _allowAutoRedirect;
private Response<Ocelot.Request.Request> _response;
private string _reRouteKey;
private readonly bool _useTracing;
public HttpRequestCreatorTests()
{
_requestCreator = new HttpRequestCreator();
_isQos = true;
_qoSProvider = new NoQoSProvider();
_useCookieContainer = false;
_allowAutoRedirect = false;
_requestMessage = new HttpRequestMessage();
}
[Fact]
public void ShouldBuildRequest()
{
this.When(x => x.WhenIBuildARequest())
.Then(x => x.ThenTheRequestContainsTheRequestMessage())
.Then(x => x.ThenTheRequestContainsTheIsQos())
.Then(x => x.ThenTheRequestContainsTheQosProvider())
.Then(x => x.ThenTheRequestContainsUseCookieContainer())
.Then(x => x.ThenTheRequestContainsUseTracing())
.Then(x => x.ThenTheRequestContainsAllowAutoRedirect())
.BDDfy();
}
private void WhenIBuildARequest()
{
_response = _requestCreator.Build(_requestMessage,
_isQos, _qoSProvider, _useCookieContainer, _allowAutoRedirect, _reRouteKey, _useTracing)
.GetAwaiter()
.GetResult();
}
private void ThenTheRequestContainsTheRequestMessage()
{
_response.Data.HttpRequestMessage.ShouldBe(_requestMessage);
}
private void ThenTheRequestContainsTheIsQos()
{
_response.Data.IsQos.ShouldBe(_isQos);
}
private void ThenTheRequestContainsTheQosProvider()
{
_response.Data.QosProvider.ShouldBe(_qoSProvider);
}
private void ThenTheRequestContainsUseCookieContainer()
{
_response.Data.UseCookieContainer.ShouldBe(_useCookieContainer);
}
private void ThenTheRequestContainsUseTracing()
{
_response.Data.IsTracing.ShouldBe(_useTracing);
}
private void ThenTheRequestContainsAllowAutoRedirect()
{
_response.Data.AllowAutoRedirect.ShouldBe(_allowAutoRedirect);
}
}
}

View File

@ -1,13 +1,15 @@
namespace Ocelot.UnitTests.RequestId
using Ocelot.Middleware;
namespace Ocelot.UnitTests.RequestId
{
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.Infrastructure.RequestData;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Ocelot.Configuration.Builder;
using Ocelot.DownstreamRouteFinder;
@ -19,22 +21,32 @@
using TestStack.BDDfy;
using Xunit;
public class ReRouteRequestIdMiddlewareTests : ServerHostedMiddlewareTest
public class ReRouteRequestIdMiddlewareTests
{
private readonly HttpRequestMessage _downstreamRequest;
private Response<DownstreamRoute> _downstreamRoute;
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();
ScopedRepository
.Setup(sr => sr.Get<HttpRequestMessage>("DownstreamRequest"))
.Returns(new OkResponse<HttpRequestMessage>(_downstreamRequest));
GivenTheTestServerIsConfigured();
_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 = async context => {
context.HttpContext.Response.Headers.Add("LSRequestId", context.HttpContext.TraceIdentifier);
};
_middleware = new ReRouteRequestIdMiddleware(_next, _loggerFactory.Object, _repo.Object);
_downstreamContext.DownstreamRequest = _downstreamRequest;
}
[Fact]
@ -42,8 +54,11 @@
{
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithRequestIdKey("LSRequestId")
.WithDownstreamReRoute(new DownstreamReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithRequestIdKey("LSRequestId")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build())
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
@ -62,10 +77,13 @@
{
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithRequestIdKey("LSRequestId")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
.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())
@ -79,10 +97,13 @@
{
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithRequestIdKey("LSRequestId")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
.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();
@ -100,10 +121,13 @@
{
var downstreamRoute = new DownstreamRoute(new List<PlaceholderNameAndValue>(),
new ReRouteBuilder()
.WithDownstreamPathTemplate("any old string")
.WithRequestIdKey("LSRequestId")
.WithUpstreamHttpMethod(new List<string> { "Get" })
.Build());
.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();
@ -116,67 +140,57 @@
.BDDfy();
}
private void WhenICallTheMiddleware()
{
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void GivenThereIsNoGlobalRequestId()
{
ScopedRepository.Setup(x => x.Get<string>("RequestId")).Returns(new OkResponse<string>(null));
_repo.Setup(x => x.Get<string>("RequestId")).Returns(new OkResponse<string>(null));
}
private void GivenTheRequestIdWasSetGlobally()
{
ScopedRepository.Setup(x => x.Get<string>("RequestId")).Returns(new OkResponse<string>("alreadyset"));
_repo.Setup(x => x.Get<string>("RequestId")).Returns(new OkResponse<string>("alreadyset"));
}
private void ThenTheRequestIdIsSaved()
{
ScopedRepository.Verify(x => x.Add<string>("RequestId", _value), Times.Once);
_repo.Verify(x => x.Add<string>("RequestId", _value), Times.Once);
}
private void ThenTheRequestIdIsUpdated()
{
ScopedRepository.Verify(x => x.Update<string>("RequestId", _value), Times.Once);
_repo.Verify(x => x.Update<string>("RequestId", _value), Times.Once);
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(ScopedRepository.Object);
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseRequestIdMiddleware();
app.Run(x =>
{
x.Response.Headers.Add("LSRequestId", x.TraceIdentifier);
return Task.CompletedTask;
});
}
private void GivenTheDownStreamRouteIs(DownstreamRoute downstreamRoute)
{
_downstreamRoute = new OkResponse<DownstreamRoute>(downstreamRoute);
ScopedRepository
.Setup(x => x.Get<DownstreamRoute>(It.IsAny<string>()))
.Returns(_downstreamRoute);
_downstreamContext.TemplatePlaceholderNameAndValues = downstreamRoute.TemplatePlaceholderNameAndValues;
_downstreamContext.DownstreamReRoute = downstreamRoute.ReRoute.DownstreamReRoute[0];
}
private void GivenTheRequestIdIsAddedToTheRequest(string key, string value)
{
_key = key;
_value = value;
Client.DefaultRequestHeaders.TryAddWithoutValidation(_key, _value);
_downstreamContext.HttpContext.Request.Headers.TryAdd(_key, _value);
}
private void ThenTheTraceIdIsAnything()
{
ResponseMessage.Headers.GetValues("LSRequestId").First().ShouldNotBeNullOrEmpty();
StringValues value;
_downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out value);
value.First().ShouldNotBeNullOrEmpty();
}
private void ThenTheTraceIdIs(string expected)
{
ResponseMessage.Headers.GetValues("LSRequestId").First().ShouldBe(expected);
StringValues value;
_downstreamContext.HttpContext.Response.Headers.TryGetValue("LSRequestId", out value);
value.First().ShouldBe(expected);
}
}
}

View File

@ -1,6 +1,9 @@
using System;
using System.Net.Http;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Errors;
using Ocelot.Requester;
using Ocelot.Responses;
using Shouldly;
@ -14,7 +17,7 @@ namespace Ocelot.UnitTests.Requester
private readonly DelegatingHandlerHandlerHouse _house;
private Mock<IDelegatingHandlerHandlerProviderFactory> _factory;
private readonly Mock<IDelegatingHandlerHandlerProvider> _provider;
private Ocelot.Request.Request _request;
private DownstreamReRoute _request;
private Response<IDelegatingHandlerHandlerProvider> _result;
public DelegatingHandlerHandlerHouseTests()
@ -27,9 +30,10 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_create_and_store_provider()
{
var request = new Ocelot.Request.Request(new HttpRequestMessage(), true, null, true, true, "key", false);
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("key").Build();
this.Given(x => GivenTheRequest(request))
this.Given(x => GivenTheRequest(reRoute))
.And(x => GivenTheProviderReturns())
.When(x => WhenIGet())
.Then(x => ThenTheFactoryIsCalled(1))
@ -40,9 +44,10 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_get_provider()
{
var request = new Ocelot.Request.Request(new HttpRequestMessage(), true, null, true, true, "key", false);
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("key").Build();
this.Given(x => GivenTheRequest(request))
this.Given(x => GivenTheRequest(reRoute))
.And(x => GivenTheProviderReturns())
.And(x => WhenIGet())
.And(x => GivenTheFactoryIsCleared())
@ -55,15 +60,34 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_return_error()
{
var request = new Ocelot.Request.Request(new HttpRequestMessage(), true, null, true, true, "key", false);
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("key").Build();
this.Given(x => GivenTheRequest(request))
this.Given(x => GivenTheRequest(reRoute))
.And(x => GivenTheProviderThrows())
.When(x => WhenIGet())
.And(x => ThenAnErrorIsReturned())
.BDDfy();
}
[Fact]
public void should_return_error_if_factory_errors()
{
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("key").Build();
this.Given(x => GivenTheRequest(reRoute))
.And(x => GivenTheProviderReturnsError())
.When(x => WhenIGet())
.Then(x => ThenAnUnknownErrorIsReturned())
.BDDfy();
}
private void ThenAnUnknownErrorIsReturned()
{
_result.IsError.ShouldBeTrue();
}
private void ThenAnErrorIsReturned()
{
_result.IsError.ShouldBeTrue();
@ -72,7 +96,7 @@ namespace Ocelot.UnitTests.Requester
private void GivenTheProviderThrows()
{
_factory.Setup(x => x.Get(It.IsAny<Ocelot.Request.Request>())).Throws<Exception>();
_factory.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Throws<Exception>();
}
private void GivenTheFactoryIsCleared()
@ -90,14 +114,19 @@ namespace Ocelot.UnitTests.Requester
_result = _house.Get(_request);
}
private void GivenTheRequest(Ocelot.Request.Request request)
private void GivenTheRequest(DownstreamReRoute request)
{
_request = request;
}
private void GivenTheProviderReturns()
{
_factory.Setup(x => x.Get(It.IsAny<Ocelot.Request.Request>())).Returns(_provider.Object);
_factory.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(new OkResponse<IDelegatingHandlerHandlerProvider>(_provider.Object));
}
private void GivenTheProviderReturnsError()
{
_factory.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(new ErrorResponse<IDelegatingHandlerHandlerProvider>(It.IsAny<Error>()));
}
private void ThenTheFactoryIsCalled(int times)

View File

@ -2,8 +2,13 @@ using System;
using System.Collections.Generic;
using System.Net.Http;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Errors;
using Ocelot.Logging;
using Ocelot.Requester;
using Ocelot.Requester.QoS;
using Ocelot.Responses;
using Shouldly;
using TestStack.BDDfy;
using Xunit;
@ -14,17 +19,27 @@ namespace Ocelot.UnitTests.Requester
{
private readonly DelegatingHandlerHandlerProviderFactory _factory;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Ocelot.Request.Request _request;
private IDelegatingHandlerHandlerProvider _provider;
private DownstreamReRoute _request;
private Response<IDelegatingHandlerHandlerProvider> _provider;
private readonly Mock<IDelegatingHandlerHandlerProvider> _allRoutesProvider;
private readonly Mock<IQosProviderHouse> _qosProviderHouse;
public DelegatingHandlerHandlerProviderFactoryTests()
{
_qosProviderHouse = new Mock<IQosProviderHouse>();
_allRoutesProvider = new Mock<IDelegatingHandlerHandlerProvider>();
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_factory = new DelegatingHandlerHandlerProviderFactory(_loggerFactory.Object, _allRoutesProvider.Object, null);
_factory = new DelegatingHandlerHandlerProviderFactory(_loggerFactory.Object, _allRoutesProvider.Object, null, _qosProviderHouse.Object);
}
private void GivenTheQosProviderHouseReturns(Response<IQoSProvider> qosProvider)
{
_qosProviderHouse
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
.Returns(qosProvider);
}
[Fact]
public void should_all_from_all_routes_provider_and_qos()
{
@ -34,9 +49,11 @@ namespace Ocelot.UnitTests.Requester
() => new FakeDelegatingHandler(1)
};
var request = new Ocelot.Request.Request(new HttpRequestMessage(), true, null, true, true, "", false);
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
this.Given(x => GivenTheFollowingRequest(request))
this.Given(x => GivenTheFollowingRequest(reRoute))
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
.And(x => GivenTheAllRoutesProviderReturns(handlers))
.When(x => WhenIGet())
.Then(x => ThenThereIsDelegatesInProvider(3))
@ -48,9 +65,10 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_return_provider_with_no_delegates()
{
var request = new Ocelot.Request.Request(new HttpRequestMessage(), false, null, true, true, "", false);
var reRoute = new DownstreamReRouteBuilder().WithIsQos(false)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
this.Given(x => GivenTheFollowingRequest(request))
this.Given(x => GivenTheFollowingRequest(reRoute))
.And(x => GivenTheAllRoutesProviderReturns())
.When(x => WhenIGet())
.Then(x => ThenNoDelegatesAreInTheProvider())
@ -60,9 +78,11 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_return_provider_with_qos_delegate()
{
var request = new Ocelot.Request.Request(new HttpRequestMessage(), true, null, true, true, "", false);
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
this.Given(x => GivenTheFollowingRequest(request))
this.Given(x => GivenTheFollowingRequest(reRoute))
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
.And(x => GivenTheAllRoutesProviderReturns())
.When(x => WhenIGet())
.Then(x => ThenThereIsDelegatesInProvider(1))
@ -70,9 +90,28 @@ namespace Ocelot.UnitTests.Requester
.BDDfy();
}
[Fact]
public void should_return_error()
{
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
this.Given(x => GivenTheFollowingRequest(reRoute))
.And(x => GivenTheQosProviderHouseReturns(new ErrorResponse<IQoSProvider>(It.IsAny<Error>())))
.And(x => GivenTheAllRoutesProviderReturns())
.When(x => WhenIGet())
.Then(x => ThenAnErrorIsReturned())
.BDDfy();
}
private void ThenAnErrorIsReturned()
{
_provider.IsError.ShouldBeTrue();
}
private void ThenTheDelegatesAreAddedCorrectly()
{
var delegates = _provider.Get();
var delegates = _provider.Data.Get();
var del = delegates[0].Invoke();
var handler = (FakeDelegatingHandler) del;
handler.Order.ShouldBe(0);
@ -94,7 +133,7 @@ namespace Ocelot.UnitTests.Requester
private void ThenItIsPolly(int i)
{
var delegates = _provider.Get();
var delegates = _provider.Data.Get();
var del = delegates[i].Invoke();
del.ShouldBeOfType<PollyCircuitBreakingDelegatingHandler>();
}
@ -102,10 +141,10 @@ namespace Ocelot.UnitTests.Requester
private void ThenThereIsDelegatesInProvider(int count)
{
_provider.ShouldNotBeNull();
_provider.Get().Count.ShouldBe(count);
_provider.Data.Get().Count.ShouldBe(count);
}
private void GivenTheFollowingRequest(Ocelot.Request.Request request)
private void GivenTheFollowingRequest(DownstreamReRoute request)
{
_request = request;
}
@ -118,7 +157,7 @@ namespace Ocelot.UnitTests.Requester
private void ThenNoDelegatesAreInTheProvider()
{
_provider.ShouldNotBeNull();
_provider.Get().Count.ShouldBe(0);
_provider.Data.Get().Count.ShouldBe(0);
}
}
}

View File

@ -2,6 +2,8 @@ using System;
using System.Collections.Generic;
using System.Net.Http;
using Moq;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Requester;
using Ocelot.Responses;
using Shouldly;
@ -18,7 +20,7 @@ namespace Ocelot.UnitTests.Requester
private IHttpClientBuilder _builderResult;
private IHttpClient _httpClient;
private HttpResponseMessage _response;
private Ocelot.Request.Request _request;
private DownstreamReRoute _request;
public HttpClientBuilderTests()
{
@ -62,13 +64,16 @@ namespace Ocelot.UnitTests.Requester
private void GivenARequest()
{
_request = new Ocelot.Request.Request(null, false, null, false, false, "", false);
var reRoute = new DownstreamReRouteBuilder().WithIsQos(false)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false)).WithReRouteKey("").Build();
_request = reRoute;
}
private void GivenTheHouseReturns()
{
_house
.Setup(x => x.Get(It.IsAny<Ocelot.Request.Request>()))
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
.Returns(new OkResponse<IDelegatingHandlerHandlerProvider>(_provider.Object));
}

View File

@ -1,13 +1,14 @@
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Moq;
using Ocelot.Logging;
using Ocelot.Requester;
using Ocelot.Requester.QoS;
using Ocelot.Responses;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using Microsoft.AspNetCore.Http;
using Ocelot.Configuration;
using Ocelot.Configuration.Builder;
using Ocelot.Middleware;
using TestStack.BDDfy;
using Xunit;
using Shouldly;
@ -21,7 +22,7 @@ namespace Ocelot.UnitTests.Requester
private Mock<IDelegatingHandlerHandlerProvider> _provider;
private Response<HttpResponseMessage> _response;
private readonly HttpClientHttpRequester _httpClientRequester;
private Ocelot.Request.Request _request;
private DownstreamContext _request;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger;
@ -30,7 +31,7 @@ namespace Ocelot.UnitTests.Requester
_provider = new Mock<IDelegatingHandlerHandlerProvider>();
_provider.Setup(x => x.Get()).Returns(new List<Func<DelegatingHandler>>());
_house = new Mock<IDelegatingHandlerHandlerHouse>();
_house.Setup(x => x.Get(It.IsAny<Ocelot.Request.Request>())).Returns(new OkResponse<IDelegatingHandlerHandlerProvider>(_provider.Object));
_house.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(new OkResponse<IDelegatingHandlerHandlerProvider>(_provider.Object));
_logger = new Mock<IOcelotLogger>();
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_loggerFactory
@ -43,7 +44,16 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_call_request_correctly()
{
this.Given(x=>x.GivenTheRequestIs(new Ocelot.Request.Request(new HttpRequestMessage() { RequestUri = new Uri("http://www.bbc.co.uk") }, false, new NoQoSProvider(), false, false, "", false)))
var reRoute = new DownstreamReRouteBuilder().WithIsQos(false)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false)).WithReRouteKey("").Build();
var context = new DownstreamContext(new DefaultHttpContext())
{
DownstreamReRoute = reRoute,
DownstreamRequest = new HttpRequestMessage() { RequestUri = new Uri("http://www.bbc.co.uk") },
};
this.Given(x=>x.GivenTheRequestIs(context))
.When(x=>x.WhenIGetResponse())
.Then(x => x.ThenTheResponseIsCalledCorrectly())
.BDDfy();
@ -52,13 +62,22 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_call_request_unable_to_complete_request()
{
this.Given(x => x.GivenTheRequestIs(new Ocelot.Request.Request(new HttpRequestMessage() { RequestUri = new Uri("http://localhost:60080") }, false, new NoQoSProvider(), false, false, "", false)))
var reRoute = new DownstreamReRouteBuilder().WithIsQos(false)
.WithHttpHandlerOptions(new HttpHandlerOptions(false, false, false)).WithReRouteKey("").Build();
var context = new DownstreamContext(new DefaultHttpContext())
{
DownstreamReRoute = reRoute,
DownstreamRequest = new HttpRequestMessage() { RequestUri = new Uri("http://localhost:60080") },
};
this.Given(x => x.GivenTheRequestIs(context))
.When(x => x.WhenIGetResponse())
.Then(x => x.ThenTheResponseIsCalledError())
.BDDfy();
}
private void GivenTheRequestIs(Ocelot.Request.Request request)
private void GivenTheRequestIs(DownstreamContext request)
{
_request = request;
}

View File

@ -1,81 +1,73 @@
using Ocelot.Configuration.Builder;
using Ocelot.Middleware;
namespace Ocelot.UnitTests.Requester
{
using Microsoft.AspNetCore.Http;
using System.Net.Http;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Ocelot.Logging;
using Ocelot.Requester;
using Ocelot.Requester.Middleware;
using Ocelot.Requester.QoS;
using Ocelot.Responses;
using TestStack.BDDfy;
using Xunit;
using Shouldly;
public class HttpRequesterMiddlewareTests : ServerHostedMiddlewareTest
public class HttpRequesterMiddlewareTests
{
private readonly Mock<IHttpRequester> _requester;
private OkResponse<HttpResponseMessage> _response;
private OkResponse<Ocelot.Request.Request> _request;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger;
private readonly HttpRequesterMiddleware _middleware;
private DownstreamContext _downstreamContext;
private OcelotRequestDelegate _next;
public HttpRequesterMiddlewareTests()
{
_requester = new Mock<IHttpRequester>();
GivenTheTestServerIsConfigured();
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<HttpRequesterMiddleware>()).Returns(_logger.Object);
_next = async context => {
//do nothing
};
_middleware = new HttpRequesterMiddleware(_next, _loggerFactory.Object, _requester.Object);
}
[Fact]
public void should_call_scoped_data_repository_correctly()
public void should_call_services_correctly()
{
this.Given(x => x.GivenTheRequestIs(new Ocelot.Request.Request(new HttpRequestMessage(),true, new NoQoSProvider(), false, false, "", false)))
this.Given(x => x.GivenTheRequestIs())
.And(x => x.GivenTheRequesterReturns(new HttpResponseMessage()))
.And(x => x.GivenTheScopedRepoReturns())
.When(x => x.WhenICallTheMiddleware())
.Then(x => x.ThenTheScopedRepoIsCalledCorrectly())
.BDDfy();
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
private void WhenICallTheMiddleware()
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(_requester.Object);
services.AddSingleton(ScopedRepository.Object);
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
private void GivenTheRequestIs()
{
app.UseHttpRequesterMiddleware();
}
private void GivenTheRequestIs(Ocelot.Request.Request request)
{
_request = new OkResponse<Ocelot.Request.Request>(request);
ScopedRepository
.Setup(x => x.Get<Ocelot.Request.Request>(It.IsAny<string>()))
.Returns(_request);
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
_downstreamContext.DownstreamReRoute = new DownstreamReRouteBuilder().Build();
}
private void GivenTheRequesterReturns(HttpResponseMessage response)
{
_response = new OkResponse<HttpResponseMessage>(response);
_requester
.Setup(x => x.GetResponse(It.IsAny<Ocelot.Request.Request>()))
.Setup(x => x.GetResponse(It.IsAny<DownstreamContext>()))
.ReturnsAsync(_response);
}
private void GivenTheScopedRepoReturns()
{
ScopedRepository
.Setup(x => x.Add(It.IsAny<string>(), _response.Data))
.Returns(new OkResponse());
}
private void ThenTheScopedRepoIsCalledCorrectly()
{
ScopedRepository
.Verify(x => x.Add("HttpResponseMessage", _response.Data), Times.Once());
_downstreamContext.DownstreamResponse.ShouldBe(_response.Data);
}
}
}

View File

@ -13,7 +13,7 @@ namespace Ocelot.UnitTests.Requester
public class QoSProviderFactoryTests
{
private readonly IQoSProviderFactory _factory;
private ReRoute _reRoute;
private DownstreamReRoute _reRoute;
private IQoSProvider _result;
private Mock<IOcelotLoggerFactory> _loggerFactory;
private Mock<IOcelotLogger> _logger;
@ -31,7 +31,7 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_return_no_qos_provider()
{
var reRoute = new ReRouteBuilder()
var reRoute = new DownstreamReRouteBuilder()
.WithUpstreamHttpMethod(new List<string> { "get" })
.WithIsQos(false)
.Build();
@ -51,7 +51,7 @@ namespace Ocelot.UnitTests.Requester
.WithExceptionsAllowedBeforeBreaking(100)
.Build();
var reRoute = new ReRouteBuilder()
var reRoute = new DownstreamReRouteBuilder()
.WithUpstreamHttpMethod(new List<string> { "get" })
.WithIsQos(true)
.WithQosOptions(qosOptions)
@ -63,7 +63,7 @@ namespace Ocelot.UnitTests.Requester
.BDDfy();
}
private void GivenAReRoute(ReRoute reRoute)
private void GivenAReRoute(DownstreamReRoute reRoute)
{
_reRoute = reRoute;
}

View File

@ -15,7 +15,7 @@ namespace Ocelot.UnitTests.Requester
private readonly QosProviderHouse _qosProviderHouse;
private Response _addResult;
private Response<IQoSProvider> _getResult;
private ReRoute _reRoute;
private DownstreamReRoute _reRoute;
private readonly Mock<IQoSProviderFactory> _factory;
public QosProviderHouseTests()
@ -27,7 +27,7 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_store_qos_provider_on_first_request()
{
var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build();
var reRoute = new DownstreamReRouteBuilder().WithReRouteKey("test").Build();
this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
.Then(x => x.ThenItIsAdded())
@ -37,7 +37,7 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_not_store_qos_provider_on_first_request()
{
var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build();
var reRoute = new DownstreamReRouteBuilder().WithReRouteKey("test").Build();
this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
.When(x => x.WhenWeGetTheQoSProvider(reRoute))
@ -48,8 +48,8 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_store_qos_providers_by_key()
{
var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build();
var reRouteTwo = new ReRouteBuilder().WithReRouteKey("testTwo").Build();
var reRoute = new DownstreamReRouteBuilder().WithReRouteKey("test").Build();
var reRouteTwo = new DownstreamReRouteBuilder().WithReRouteKey("testTwo").Build();
this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
.And(x => x.GivenThereIsAQoSProvider(reRouteTwo, new FakePollyQoSProvider()))
@ -63,7 +63,7 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_return_error_if_no_qos_provider_with_key()
{
var reRoute = new ReRouteBuilder().Build();
var reRoute = new DownstreamReRouteBuilder().Build();
this.When(x => x.WhenWeGetTheQoSProvider(reRoute))
.Then(x => x.ThenAnErrorIsReturned())
@ -73,9 +73,9 @@ namespace Ocelot.UnitTests.Requester
[Fact]
public void should_get_new_qos_provider_if_reroute_qos_provider_has_changed()
{
var reRoute = new ReRouteBuilder().WithReRouteKey("test").Build();
var reRoute = new DownstreamReRouteBuilder().WithReRouteKey("test").Build();
var reRouteTwo = new ReRouteBuilder().WithReRouteKey("test").WithIsQos(true).Build();
var reRouteTwo = new DownstreamReRouteBuilder().WithReRouteKey("test").WithIsQos(true).Build();
this.Given(x => x.GivenThereIsAQoSProvider(reRoute, new FakeQoSProvider()))
.When(x => x.WhenWeGetTheQoSProvider(reRoute))
@ -85,7 +85,7 @@ namespace Ocelot.UnitTests.Requester
.BDDfy();
}
private void WhenIGetTheReRouteWithTheSameKeyButDifferentQosProvider(ReRoute reRoute)
private void WhenIGetTheReRouteWithTheSameKeyButDifferentQosProvider(DownstreamReRoute reRoute)
{
_reRoute = reRoute;
_factory.Setup(x => x.Get(_reRoute)).Returns(new FakePollyQoSProvider());
@ -112,7 +112,7 @@ namespace Ocelot.UnitTests.Requester
}
private void GivenThereIsAQoSProvider(ReRoute reRoute, IQoSProvider qoSProvider)
private void GivenThereIsAQoSProvider(DownstreamReRoute reRoute, IQoSProvider qoSProvider)
{
_reRoute = reRoute;
_qoSProvider = qoSProvider;
@ -120,7 +120,7 @@ namespace Ocelot.UnitTests.Requester
_getResult = _qosProviderHouse.Get(reRoute);
}
private void WhenWeGetTheQoSProvider(ReRoute reRoute)
private void WhenWeGetTheQoSProvider(DownstreamReRoute reRoute)
{
_getResult = _qosProviderHouse.Get(reRoute);
}

View File

@ -1,32 +1,45 @@
namespace Ocelot.UnitTests.Responder
using System.Collections.Generic;
using Ocelot.Middleware;
namespace Ocelot.UnitTests.Responder
{
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Ocelot.DownstreamRouteFinder.Middleware;
using System.Net.Http;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Moq;
using Ocelot.DownstreamRouteFinder.Finder;
using Ocelot.Errors;
using Ocelot.Logging;
using Ocelot.Requester;
using Ocelot.Responder;
using Ocelot.Responder.Middleware;
using Ocelot.Responses;
using TestStack.BDDfy;
using Xunit;
public class ResponderMiddlewareTests : ServerHostedMiddlewareTest
public class ResponderMiddlewareTests
{
private readonly Mock<IHttpResponder> _responder;
private readonly Mock<IErrorsToHttpStatusCodeMapper> _codeMapper;
private OkResponse<HttpResponseMessage> _response;
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>();
GivenTheTestServerIsConfigured();
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
_loggerFactory = new Mock<IOcelotLoggerFactory>();
_logger = new Mock<IOcelotLogger>();
_loggerFactory.Setup(x => x.CreateLogger<ResponderMiddleware>()).Returns(_logger.Object);
_next = async context => {
//do nothing
};
_middleware = new ResponderMiddleware(_next, _responder.Object, _loggerFactory.Object, _codeMapper.Object);
}
[Fact]
@ -39,7 +52,6 @@
.BDDfy();
}
[Fact]
public void should_return_any_errors()
{
@ -50,33 +62,19 @@
.BDDfy();
}
protected override void GivenTheTestServerServicesAreConfigured(IServiceCollection services)
private void WhenICallTheMiddleware()
{
services.AddSingleton<IOcelotLoggerFactory, AspDotNetLoggerFactory>();
services.AddLogging();
services.AddSingleton(_codeMapper.Object);
services.AddSingleton(_responder.Object);
services.AddSingleton(ScopedRepository.Object);
}
protected override void GivenTheTestServerPipelineIsConfigured(IApplicationBuilder app)
{
app.UseResponderMiddleware();
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
}
private void GivenTheHttpResponseMessageIs(HttpResponseMessage response)
{
_response = new OkResponse<HttpResponseMessage>(response);
ScopedRepository
.Setup(x => x.Get<HttpResponseMessage>(It.IsAny<string>()))
.Returns(_response);
_downstreamContext.DownstreamResponse = response;
}
private void GivenThereAreNoPipelineErrors()
{
ScopedRepository
.Setup(x => x.Get<bool>(It.IsAny<string>()))
.Returns(new OkResponse<bool>(false));
_downstreamContext.Errors = new List<Error>();
}
private void ThenThereAreNoErrors()
@ -86,11 +84,7 @@
private void GivenThereArePipelineErrors(Error error)
{
ScopedRepository
.Setup(x => x.Get<bool>("OcelotMiddlewareError"))
.Returns(new OkResponse<bool>(true));
ScopedRepository.Setup(x => x.Get<List<Error>>("OcelotMiddlewareErrors"))
.Returns(new OkResponse<List<Error>>(new List<Error>() { error }));
_downstreamContext.Errors = new List<Error>(){error};
}
}
}

View File

@ -16,7 +16,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
private ServiceProviderConfiguration _serviceConfig;
private IServiceDiscoveryProvider _result;
private readonly ServiceDiscoveryProviderFactory _factory;
private ReRoute _reRoute;
private DownstreamReRoute _reRoute;
private Mock<IOcelotLoggerFactory> _loggerFactory;
public ServiceProviderFactoryTests()
@ -31,7 +31,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
var serviceConfig = new ServiceProviderConfigurationBuilder()
.Build();
var reRoute = new ReRouteBuilder().Build();
var reRoute = new DownstreamReRouteBuilder().Build();
this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute))
.When(x => x.WhenIGetTheServiceProvider())
@ -51,7 +51,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
new DownstreamHostAndPort("abc.com", 80)
};
var reRoute = new ReRouteBuilder().WithDownstreamAddresses(downstreamAddresses).Build();
var reRoute = new DownstreamReRouteBuilder().WithDownstreamAddresses(downstreamAddresses).Build();
this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute))
.When(x => x.WhenIGetTheServiceProvider())
@ -60,6 +60,23 @@ namespace Ocelot.UnitTests.ServiceDiscovery
.BDDfy();
}
[Fact]
public void should_return_consul_service_provider()
{
var reRoute = new DownstreamReRouteBuilder()
.WithServiceName("product")
.WithUseServiceDiscovery(true)
.Build();
var serviceConfig = new ServiceProviderConfigurationBuilder()
.Build();
this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute))
.When(x => x.WhenIGetTheServiceProvider())
.Then(x => x.ThenTheServiceProviderIs<ConsulServiceDiscoveryProvider>())
.BDDfy();
}
private void ThenTheFollowingServicesAreReturned(List<DownstreamHostAndPort> downstreamAddresses)
{
var result = (ConfigurationServiceProvider)_result;
@ -75,24 +92,7 @@ namespace Ocelot.UnitTests.ServiceDiscovery
}
}
[Fact]
public void should_return_consul_service_provider()
{
var reRoute = new ReRouteBuilder()
.WithServiceName("product")
.WithUseServiceDiscovery(true)
.Build();
var serviceConfig = new ServiceProviderConfigurationBuilder()
.Build();
this.Given(x => x.GivenTheReRoute(serviceConfig, reRoute))
.When(x => x.WhenIGetTheServiceProvider())
.Then(x => x.ThenTheServiceProviderIs<ConsulServiceDiscoveryProvider>())
.BDDfy();
}
private void GivenTheReRoute(ServiceProviderConfiguration serviceConfig, ReRoute reRoute)
private void GivenTheReRoute(ServiceProviderConfiguration serviceConfig, DownstreamReRoute reRoute)
{
_serviceConfig = serviceConfig;
_reRoute = reRoute;