mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:42:50 +08:00
Merge branch 'release-4.0.0'
This commit is contained in:
commit
ae5b86ef61
@ -1,74 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RuleSet Name="Rules for StyleCop.Analyzers" Description="Code analysis rules for StyleCop.Analyzers.csproj." ToolsVersion="14.0">
|
<RuleSet Name="Rules for StyleCop.Analyzers" Description="Code analysis rules for StyleCop.Analyzers.csproj." ToolsVersion="15.0">
|
||||||
<Rules AnalyzerId="AsyncUsageAnalyzers" RuleNamespace="AsyncUsageAnalyzers">
|
<Rules AnalyzerId="AsyncUsageAnalyzers" RuleNamespace="AsyncUsageAnalyzers">
|
||||||
<Rule Id="AvoidAsyncSuffix" Action="None" />
|
<Rule Id="AvoidAsyncSuffix" Action="None" />
|
||||||
<Rule Id="AvoidAsyncVoid" Action="None" />
|
<Rule Id="AvoidAsyncVoid" Action="Error" />
|
||||||
<Rule Id="UseAsyncSuffix" Action="None" />
|
<Rule Id="UseAsyncSuffix" Action="None" />
|
||||||
<Rule Id="UseConfigureAwait" Action="None" />
|
<Rule Id="UseConfigureAwait" Action="Error" />
|
||||||
</Rules>
|
|
||||||
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
|
|
||||||
<Rule Id="CA1001" Action="None" />
|
|
||||||
<Rule Id="CA1009" Action="None" />
|
|
||||||
<Rule Id="CA1016" Action="None" />
|
|
||||||
<Rule Id="CA1033" Action="None" />
|
|
||||||
<Rule Id="CA1049" Action="None" />
|
|
||||||
<Rule Id="CA1060" Action="None" />
|
|
||||||
<Rule Id="CA1061" Action="None" />
|
|
||||||
<Rule Id="CA1063" Action="None" />
|
|
||||||
<Rule Id="CA1065" Action="None" />
|
|
||||||
<Rule Id="CA1301" Action="None" />
|
|
||||||
<Rule Id="CA1400" Action="None" />
|
|
||||||
<Rule Id="CA1401" Action="None" />
|
|
||||||
<Rule Id="CA1403" Action="None" />
|
|
||||||
<Rule Id="CA1404" Action="None" />
|
|
||||||
<Rule Id="CA1405" Action="None" />
|
|
||||||
<Rule Id="CA1410" Action="None" />
|
|
||||||
<Rule Id="CA1415" Action="None" />
|
|
||||||
<Rule Id="CA1821" Action="None" />
|
|
||||||
<Rule Id="CA1900" Action="None" />
|
|
||||||
<Rule Id="CA1901" Action="None" />
|
|
||||||
<Rule Id="CA2002" Action="None" />
|
|
||||||
<Rule Id="CA2100" Action="None" />
|
|
||||||
<Rule Id="CA2101" Action="None" />
|
|
||||||
<Rule Id="CA2108" Action="None" />
|
|
||||||
<Rule Id="CA2111" Action="None" />
|
|
||||||
<Rule Id="CA2112" Action="None" />
|
|
||||||
<Rule Id="CA2114" Action="None" />
|
|
||||||
<Rule Id="CA2116" Action="None" />
|
|
||||||
<Rule Id="CA2117" Action="None" />
|
|
||||||
<Rule Id="CA2122" Action="None" />
|
|
||||||
<Rule Id="CA2123" Action="None" />
|
|
||||||
<Rule Id="CA2124" Action="None" />
|
|
||||||
<Rule Id="CA2126" Action="None" />
|
|
||||||
<Rule Id="CA2131" Action="None" />
|
|
||||||
<Rule Id="CA2132" Action="None" />
|
|
||||||
<Rule Id="CA2133" Action="None" />
|
|
||||||
<Rule Id="CA2134" Action="None" />
|
|
||||||
<Rule Id="CA2137" Action="None" />
|
|
||||||
<Rule Id="CA2138" Action="None" />
|
|
||||||
<Rule Id="CA2140" Action="None" />
|
|
||||||
<Rule Id="CA2141" Action="None" />
|
|
||||||
<Rule Id="CA2146" Action="None" />
|
|
||||||
<Rule Id="CA2147" Action="None" />
|
|
||||||
<Rule Id="CA2149" Action="None" />
|
|
||||||
<Rule Id="CA2200" Action="None" />
|
|
||||||
<Rule Id="CA2202" Action="None" />
|
|
||||||
<Rule Id="CA2207" Action="None" />
|
|
||||||
<Rule Id="CA2212" Action="None" />
|
|
||||||
<Rule Id="CA2213" Action="None" />
|
|
||||||
<Rule Id="CA2214" Action="None" />
|
|
||||||
<Rule Id="CA2216" Action="None" />
|
|
||||||
<Rule Id="CA2220" Action="None" />
|
|
||||||
<Rule Id="CA2229" Action="None" />
|
|
||||||
<Rule Id="CA2231" Action="None" />
|
|
||||||
<Rule Id="CA2232" Action="None" />
|
|
||||||
<Rule Id="CA2235" Action="None" />
|
|
||||||
<Rule Id="CA2236" Action="None" />
|
|
||||||
<Rule Id="CA2237" Action="None" />
|
|
||||||
<Rule Id="CA2238" Action="None" />
|
|
||||||
<Rule Id="CA2240" Action="None" />
|
|
||||||
<Rule Id="CA2241" Action="None" />
|
|
||||||
<Rule Id="CA2242" Action="None" />
|
|
||||||
</Rules>
|
</Rules>
|
||||||
<Rules AnalyzerId="Microsoft.CodeAnalysis.CSharp.Features" RuleNamespace="Microsoft.CodeAnalysis.CSharp.Features">
|
<Rules AnalyzerId="Microsoft.CodeAnalysis.CSharp.Features" RuleNamespace="Microsoft.CodeAnalysis.CSharp.Features">
|
||||||
<Rule Id="IDE0003" Action="None" />
|
<Rule Id="IDE0003" Action="None" />
|
||||||
@ -87,12 +23,12 @@
|
|||||||
<Rule Id="SA1013" Action="None" />
|
<Rule Id="SA1013" Action="None" />
|
||||||
<Rule Id="SA1015" Action="None" />
|
<Rule Id="SA1015" Action="None" />
|
||||||
<Rule Id="SA1016" Action="None" />
|
<Rule Id="SA1016" Action="None" />
|
||||||
<Rule Id="SA1021" Action="None" />
|
<Rule Id="SA1021" Action="Error" />
|
||||||
<Rule Id="SA1022" Action="None" />
|
<Rule Id="SA1022" Action="Error" />
|
||||||
<Rule Id="SA1024" Action="None" />
|
<Rule Id="SA1024" Action="None" />
|
||||||
<Rule Id="SA1026" Action="None" />
|
<Rule Id="SA1026" Action="None" />
|
||||||
<Rule Id="SA1028" Action="None" />
|
<Rule Id="SA1028" Action="None" />
|
||||||
<Rule Id="SA1100" Action="None" />
|
<Rule Id="SA1100" Action="Error" />
|
||||||
<Rule Id="SA1101" Action="None" />
|
<Rule Id="SA1101" Action="None" />
|
||||||
<Rule Id="SA1106" Action="None" />
|
<Rule Id="SA1106" Action="None" />
|
||||||
<Rule Id="SA1111" Action="None" />
|
<Rule Id="SA1111" Action="None" />
|
||||||
@ -100,11 +36,11 @@
|
|||||||
<Rule Id="SA1116" Action="None" />
|
<Rule Id="SA1116" Action="None" />
|
||||||
<Rule Id="SA1117" Action="None" />
|
<Rule Id="SA1117" Action="None" />
|
||||||
<Rule Id="SA1118" Action="None" />
|
<Rule Id="SA1118" Action="None" />
|
||||||
<Rule Id="SA1119" Action="None" />
|
<Rule Id="SA1119" Action="Error" />
|
||||||
<Rule Id="SA1121" Action="None" />
|
<Rule Id="SA1121" Action="Error" />
|
||||||
<Rule Id="SA1122" Action="None" />
|
<Rule Id="SA1122" Action="None" />
|
||||||
<Rule Id="SA1128" Action="None" />
|
<Rule Id="SA1128" Action="None" />
|
||||||
<Rule Id="SA1133" Action="None" />
|
<Rule Id="SA1133" Action="Error" />
|
||||||
<Rule Id="SA1200" Action="None" />
|
<Rule Id="SA1200" Action="None" />
|
||||||
<Rule Id="SA1201" Action="None" />
|
<Rule Id="SA1201" Action="None" />
|
||||||
<Rule Id="SA1202" Action="None" />
|
<Rule Id="SA1202" Action="None" />
|
||||||
@ -116,37 +52,37 @@
|
|||||||
<Rule Id="SA1214" Action="None" />
|
<Rule Id="SA1214" Action="None" />
|
||||||
<Rule Id="SA1216" Action="None" />
|
<Rule Id="SA1216" Action="None" />
|
||||||
<Rule Id="SA1300" Action="None" />
|
<Rule Id="SA1300" Action="None" />
|
||||||
<Rule Id="SA1302" Action="None" />
|
<Rule Id="SA1302" Action="Error" />
|
||||||
<Rule Id="SA1303" Action="None" />
|
<Rule Id="SA1303" Action="None" />
|
||||||
<Rule Id="SA1304" Action="None" />
|
<Rule Id="SA1304" Action="Error" />
|
||||||
<Rule Id="SA1305" Action="None" />
|
<Rule Id="SA1305" Action="None" />
|
||||||
<Rule Id="SA1309" Action="None" />
|
<Rule Id="SA1309" Action="None" />
|
||||||
<Rule Id="SA1310" Action="None" />
|
<Rule Id="SA1310" Action="None" />
|
||||||
<Rule Id="SA1311" Action="None" />
|
<Rule Id="SA1311" Action="Error" />
|
||||||
<Rule Id="SA1400" Action="None" />
|
<Rule Id="SA1400" Action="None" />
|
||||||
<Rule Id="SA1401" Action="None" />
|
<Rule Id="SA1401" Action="None" />
|
||||||
<Rule Id="SA1402" Action="None" />
|
<Rule Id="SA1402" Action="None" />
|
||||||
<Rule Id="SA1403" Action="None" />
|
<Rule Id="SA1403" Action="Error" />
|
||||||
<Rule Id="SA1404" Action="None" />
|
<Rule Id="SA1404" Action="Error" />
|
||||||
<Rule Id="SA1405" Action="None" />
|
<Rule Id="SA1405" Action="Error" />
|
||||||
<Rule Id="SA1406" Action="None" />
|
<Rule Id="SA1406" Action="Error" />
|
||||||
<Rule Id="SA1407" Action="None" />
|
<Rule Id="SA1407" Action="Error" />
|
||||||
<Rule Id="SA1408" Action="None" />
|
<Rule Id="SA1408" Action="None" />
|
||||||
<Rule Id="SA1410" Action="None" />
|
<Rule Id="SA1410" Action="Error" />
|
||||||
<Rule Id="SA1411" Action="None" />
|
<Rule Id="SA1411" Action="Error" />
|
||||||
<Rule Id="SA1412" Action="None" />
|
<Rule Id="SA1412" Action="None" />
|
||||||
<Rule Id="SA1500" Action="None" />
|
<Rule Id="SA1500" Action="None" />
|
||||||
<Rule Id="SA1502" Action="None" />
|
<Rule Id="SA1502" Action="None" />
|
||||||
<Rule Id="SA1516" Action="None" />
|
<Rule Id="SA1516" Action="None" />
|
||||||
<Rule Id="SA1600" Action="None" />
|
<Rule Id="SA1600" Action="None" />
|
||||||
<Rule Id="SA1603" Action="None" />
|
<Rule Id="SA1603" Action="Error" />
|
||||||
<Rule Id="SA1609" Action="None" />
|
<Rule Id="SA1609" Action="Error" />
|
||||||
|
<Rule Id="SA1611" Action="None" />
|
||||||
<Rule Id="SA1623" Action="None" />
|
<Rule Id="SA1623" Action="None" />
|
||||||
<Rule Id="SA1633" Action="None" />
|
<Rule Id="SA1633" Action="None" />
|
||||||
<Rule Id="SA1636" Action="None" />
|
<Rule Id="SA1636" Action="Error" />
|
||||||
<Rule Id="SA1642" Action="None" />
|
<Rule Id="SA1642" Action="Error" />
|
||||||
<Rule Id="SA1643" Action="None" />
|
<Rule Id="SA1643" Action="Error" />
|
||||||
<Rule Id="SA1652" Action="None" />
|
<Rule Id="SA1652" Action="None" />
|
||||||
|
|
||||||
</Rules>
|
</Rules>
|
||||||
</RuleSet>
|
</RuleSet>
|
@ -4,28 +4,21 @@ Delegating Handers
|
|||||||
Ocelot allows the user to add delegating handlers to the HttpClient transport. This feature was requested `GitHub #208 <https://github.com/TomPallister/Ocelot/issues/208>`_ and I decided that it was going to be useful in various ways.
|
Ocelot allows the user to add delegating handlers to the HttpClient transport. This feature was requested `GitHub #208 <https://github.com/TomPallister/Ocelot/issues/208>`_ and I decided that it was going to be useful in various ways.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
^^^^^^
|
^^^^^
|
||||||
|
|
||||||
In order to add delegating handlers to the HttpClient transport you need to do the following.
|
In order to add delegating handlers to the HttpClient transport you need to do the following.
|
||||||
|
|
||||||
.. code-block:: csharp
|
This will register the Handlers as singletons. Because Ocelot caches the HttpClient for the downstream services to avoid
|
||||||
|
socket exhaustion (well known http client issue) you can only register singleton handlers.
|
||||||
services.AddOcelot()
|
|
||||||
.AddDelegatingHandler(() => new FakeHandler())
|
|
||||||
.AddDelegatingHandler(() => new FakeHandler());
|
|
||||||
|
|
||||||
Or for singleton like behaviour..
|
|
||||||
|
|
||||||
.. code-block:: csharp
|
.. code-block:: csharp
|
||||||
|
|
||||||
var handlerOne = new FakeHandler();
|
|
||||||
var handlerTwo = new FakeHandler();
|
|
||||||
|
|
||||||
services.AddOcelot()
|
services.AddOcelot()
|
||||||
.AddDelegatingHandler(() => handlerOne)
|
.AddDelegatingHandler<FakeHandler>()
|
||||||
.AddDelegatingHandler(() => handlerTwo);
|
.AddDelegatingHandler<FakeHandlerTwo>()
|
||||||
|
|
||||||
You can have as many DelegatingHandlers as you want and they are run in a first in first out order. If you are using Ocelot's QoS functionality then that will always be run after your last delegating handler.
|
You can have as many DelegatingHandlers as you want and they are run in a first in first out order. If you are using Ocelot's QoS functionality then that will always be run after your last delegating handler. If you are also registering handlers in DI these will be
|
||||||
|
run first.
|
||||||
|
|
||||||
In order to create a class that can be used a delegating handler it must look as follows
|
In order to create a class that can be used a delegating handler it must look as follows
|
||||||
|
|
||||||
|
BIN
docs/images/OcelotServiceFabric.jpg
Normal file
BIN
docs/images/OcelotServiceFabric.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
@ -36,3 +36,7 @@ Multiple Instances
|
|||||||
With Consul
|
With Consul
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
.. image:: ../images/OcelotMultipleInstancesConsul.jpg
|
.. image:: ../images/OcelotMultipleInstancesConsul.jpg
|
||||||
|
|
||||||
|
With Service Fabric
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
.. image:: ../images/OcelotServiceFabric.jpg
|
||||||
|
@ -6,3 +6,27 @@ Ocelot does not support...
|
|||||||
* Chunked Encoding - Ocelot will always get the body size and return Content-Length header. Sorry if this doesn't work for your use case!
|
* Chunked Encoding - Ocelot will always get the body size and return Content-Length header. Sorry if this doesn't work for your use case!
|
||||||
|
|
||||||
* Fowarding a host header - The host header that you send to Ocelot will not be forwarded to the downstream service. Obviously this would break everything :(
|
* Fowarding a host header - The host header that you send to Ocelot will not be forwarded to the downstream service. Obviously this would break everything :(
|
||||||
|
|
||||||
|
* Swagger - I have looked multiple times at building swagger.json out of the Ocelot configuration.json but it doesnt fit into the vision I have for Ocelot. If you would like to have Swagger in Ocelot then you must roll your own swagger.json and do the following in your Startup.cs or Program.cs. The code sample below registers a piece of middleware that loads your hand rolled swagger.json and returns it on /swagger/v1/swagger.json. It then registers the SwaggerUI middleware from Swashbuckle.AspNetCore
|
||||||
|
|
||||||
|
.. code-block:: csharp
|
||||||
|
|
||||||
|
app.Map("/swagger/v1/swagger.json", b =>
|
||||||
|
{
|
||||||
|
b.Run(async x => {
|
||||||
|
var json = File.ReadAllText("swagger.json");
|
||||||
|
await x.Response.WriteAsync(json);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
app.UseSwaggerUI(c =>
|
||||||
|
{
|
||||||
|
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Ocelot");
|
||||||
|
});
|
||||||
|
|
||||||
|
app.UseOcelot().Wait();
|
||||||
|
|
||||||
|
The main reasons why I don't think Swagger makes sense is we already hand roll our definition in configuration.json. If we want people developing against Ocelot to be able to see what routes are available then either share the configuration.json with them (This should be as easy as granting access to a repo etc) or use the Ocelot administration API so that they can query Ocelot for the configuration.
|
||||||
|
|
||||||
|
In addition to this many people will configure Ocelot to proxy all traffic like /products/{everything} to there product service and you would not be describing what is actually available if you parsed this and turned it into a Swagger path. Also Ocelot has no concept of the models that the downstream services can return and linking to the above problem the same endpoint can return multiple models. Ocelot does not know what models might be used in POST, PUT etc so it all gets a bit messy and finally the Swashbuckle package doesnt reload swagger.json if it changes during runtime. Ocelot's configuration can change during runtime so the Swagger and Ocelot information would not match. Unless I rolled my own Swagger implementation.
|
||||||
|
|
||||||
|
If the user wants something to easily test against the Ocelot API then I suggest using Postman as a simple way to do this. It might even be possible to write something that maps configuration.json to the postman json spec. However I don't intend to do this.
|
@ -18,7 +18,7 @@ namespace Ocelot.Configuration.Repository
|
|||||||
_configFilePath = $"{AppContext.BaseDirectory}/configuration{(string.IsNullOrEmpty(hostingEnvironment.EnvironmentName) ? string.Empty : ".")}{hostingEnvironment.EnvironmentName}.json";
|
_configFilePath = $"{AppContext.BaseDirectory}/configuration{(string.IsNullOrEmpty(hostingEnvironment.EnvironmentName) ? string.Empty : ".")}{hostingEnvironment.EnvironmentName}.json";
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Response<FileConfiguration>> Get()
|
public Task<Response<FileConfiguration>> Get()
|
||||||
{
|
{
|
||||||
string jsonConfiguration;
|
string jsonConfiguration;
|
||||||
|
|
||||||
@ -29,10 +29,10 @@ namespace Ocelot.Configuration.Repository
|
|||||||
|
|
||||||
var fileConfiguration = JsonConvert.DeserializeObject<FileConfiguration>(jsonConfiguration);
|
var fileConfiguration = JsonConvert.DeserializeObject<FileConfiguration>(jsonConfiguration);
|
||||||
|
|
||||||
return new OkResponse<FileConfiguration>(fileConfiguration);
|
return Task.FromResult<Response<FileConfiguration>>(new OkResponse<FileConfiguration>(fileConfiguration));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Response> Set(FileConfiguration fileConfiguration)
|
public Task<Response> Set(FileConfiguration fileConfiguration)
|
||||||
{
|
{
|
||||||
string jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
|
string jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ namespace Ocelot.Configuration.Repository
|
|||||||
System.IO.File.WriteAllText(_configFilePath, jsonConfiguration);
|
System.IO.File.WriteAllText(_configFilePath, jsonConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new OkResponse();
|
return Task.FromResult<Response>(new OkResponse());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,19 +12,19 @@ namespace Ocelot.Configuration.Repository
|
|||||||
|
|
||||||
private IOcelotConfiguration _ocelotConfiguration;
|
private IOcelotConfiguration _ocelotConfiguration;
|
||||||
|
|
||||||
public async Task<Response<IOcelotConfiguration>> Get()
|
public Task<Response<IOcelotConfiguration>> Get()
|
||||||
{
|
{
|
||||||
return new OkResponse<IOcelotConfiguration>(_ocelotConfiguration);
|
return Task.FromResult<Response<IOcelotConfiguration>>(new OkResponse<IOcelotConfiguration>(_ocelotConfiguration));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Response> AddOrReplace(IOcelotConfiguration ocelotConfiguration)
|
public Task<Response> AddOrReplace(IOcelotConfiguration ocelotConfiguration)
|
||||||
{
|
{
|
||||||
lock (LockObject)
|
lock (LockObject)
|
||||||
{
|
{
|
||||||
_ocelotConfiguration = ocelotConfiguration;
|
_ocelotConfiguration = ocelotConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new OkResponse();
|
return Task.FromResult<Response>(new OkResponse());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,16 +3,22 @@ using CacheManager.Core;
|
|||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using IdentityServer4.AccessTokenValidation;
|
using IdentityServer4.AccessTokenValidation;
|
||||||
|
using Ocelot.Requester;
|
||||||
|
|
||||||
namespace Ocelot.DependencyInjection
|
namespace Ocelot.DependencyInjection
|
||||||
{
|
{
|
||||||
public interface IOcelotBuilder
|
public interface IOcelotBuilder
|
||||||
{
|
{
|
||||||
IOcelotBuilder AddStoreOcelotConfigurationInConsul();
|
IOcelotBuilder AddStoreOcelotConfigurationInConsul();
|
||||||
|
|
||||||
IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings);
|
IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings);
|
||||||
|
|
||||||
IOcelotBuilder AddOpenTracing(Action<ButterflyOptions> settings);
|
IOcelotBuilder AddOpenTracing(Action<ButterflyOptions> settings);
|
||||||
|
|
||||||
IOcelotAdministrationBuilder AddAdministration(string path, string secret);
|
IOcelotAdministrationBuilder AddAdministration(string path, string secret);
|
||||||
|
|
||||||
IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions);
|
IOcelotAdministrationBuilder AddAdministration(string path, Action<IdentityServerAuthenticationOptions> configOptions);
|
||||||
IOcelotBuilder AddDelegatingHandler(Func<DelegatingHandler> delegatingHandler);
|
|
||||||
|
IOcelotBuilder AddDelegatingHandler<T>() where T : DelegatingHandler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,6 @@ namespace Ocelot.DependencyInjection
|
|||||||
{
|
{
|
||||||
private readonly IServiceCollection _services;
|
private readonly IServiceCollection _services;
|
||||||
private readonly IConfiguration _configurationRoot;
|
private readonly IConfiguration _configurationRoot;
|
||||||
private readonly IDelegatingHandlerHandlerProvider _provider;
|
|
||||||
|
|
||||||
public OcelotBuilder(IServiceCollection services, IConfiguration configurationRoot)
|
public OcelotBuilder(IServiceCollection services, IConfiguration configurationRoot)
|
||||||
{
|
{
|
||||||
@ -120,8 +119,7 @@ namespace Ocelot.DependencyInjection
|
|||||||
_services.TryAddSingleton<IRequestMapper, RequestMapper>();
|
_services.TryAddSingleton<IRequestMapper, RequestMapper>();
|
||||||
_services.TryAddSingleton<IHttpHandlerOptionsCreator, HttpHandlerOptionsCreator>();
|
_services.TryAddSingleton<IHttpHandlerOptionsCreator, HttpHandlerOptionsCreator>();
|
||||||
_services.TryAddSingleton<IDownstreamAddressesCreator, DownstreamAddressesCreator>();
|
_services.TryAddSingleton<IDownstreamAddressesCreator, DownstreamAddressesCreator>();
|
||||||
_services.TryAddSingleton<IDelegatingHandlerHandlerProviderFactory, DelegatingHandlerHandlerProviderFactory>();
|
_services.TryAddSingleton<IDelegatingHandlerHandlerFactory, DelegatingHandlerHandlerFactory>();
|
||||||
_services.TryAddSingleton<IDelegatingHandlerHandlerHouse, DelegatingHandlerHandlerHouse>();
|
|
||||||
|
|
||||||
// see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc
|
// see this for why we register this as singleton http://stackoverflow.com/questions/37371264/invalidoperationexception-unable-to-resolve-service-for-type-microsoft-aspnetc
|
||||||
// could maybe use a scoped data repository
|
// could maybe use a scoped data repository
|
||||||
@ -144,9 +142,6 @@ namespace Ocelot.DependencyInjection
|
|||||||
_services.AddWebEncoders();
|
_services.AddWebEncoders();
|
||||||
_services.AddSingleton<IAdministrationPath>(new NullAdministrationPath());
|
_services.AddSingleton<IAdministrationPath>(new NullAdministrationPath());
|
||||||
|
|
||||||
//these get picked out later and added to http request
|
|
||||||
_provider = new DelegatingHandlerHandlerProvider();
|
|
||||||
_services.TryAddSingleton<IDelegatingHandlerHandlerProvider>(_provider);
|
|
||||||
_services.TryAddSingleton<IMultiplexer, Multiplexer>();
|
_services.TryAddSingleton<IMultiplexer, Multiplexer>();
|
||||||
_services.TryAddSingleton<IResponseAggregator, SimpleJsonResponseAggregator>();
|
_services.TryAddSingleton<IResponseAggregator, SimpleJsonResponseAggregator>();
|
||||||
_services.AddSingleton<ITracingHandlerFactory, TracingHandlerFactory>();
|
_services.AddSingleton<ITracingHandlerFactory, TracingHandlerFactory>();
|
||||||
@ -187,9 +182,10 @@ namespace Ocelot.DependencyInjection
|
|||||||
return new OcelotAdministrationBuilder(_services, _configurationRoot);
|
return new OcelotAdministrationBuilder(_services, _configurationRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IOcelotBuilder AddDelegatingHandler(Func<DelegatingHandler> delegatingHandler)
|
public IOcelotBuilder AddDelegatingHandler<THandler>()
|
||||||
|
where THandler : DelegatingHandler
|
||||||
{
|
{
|
||||||
_provider.Add(delegatingHandler);
|
_services.AddSingleton<DelegatingHandler, THandler>();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,11 +47,28 @@
|
|||||||
|
|
||||||
var content = new ByteArrayContent(await ToByteArray(request.Body));
|
var content = new ByteArrayContent(await ToByteArray(request.Body));
|
||||||
|
|
||||||
content.Headers.TryAddWithoutValidation("Content-Type", new[] {request.ContentType});
|
content.Headers
|
||||||
|
.TryAddWithoutValidation("Content-Type", new[] {request.ContentType});
|
||||||
|
|
||||||
|
AddHeaderIfExistsOnRequest("Content-Language", content, request);
|
||||||
|
AddHeaderIfExistsOnRequest("Content-Location", content, request);
|
||||||
|
AddHeaderIfExistsOnRequest("Content-Range", content, request);
|
||||||
|
AddHeaderIfExistsOnRequest("Content-MD5", content, request);
|
||||||
|
AddHeaderIfExistsOnRequest("Content-Disposition", content, request);
|
||||||
|
AddHeaderIfExistsOnRequest("Content-Encoding", content, request);
|
||||||
|
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddHeaderIfExistsOnRequest(string key, HttpContent content, HttpRequest request)
|
||||||
|
{
|
||||||
|
if(request.Headers.ContainsKey(key))
|
||||||
|
{
|
||||||
|
content.Headers
|
||||||
|
.TryAddWithoutValidation(key, request.Headers[key].ToList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private HttpMethod MapMethod(HttpRequest request)
|
private HttpMethod MapMethod(HttpRequest request)
|
||||||
{
|
{
|
||||||
return new HttpMethod(request.Method);
|
return new HttpMethod(request.Method);
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Ocelot.Configuration;
|
|
||||||
using Ocelot.Errors;
|
|
||||||
using Ocelot.Responses;
|
|
||||||
|
|
||||||
namespace Ocelot.Requester
|
|
||||||
{
|
|
||||||
public class DelegatingHandlerHandlerHouse : IDelegatingHandlerHandlerHouse
|
|
||||||
{
|
|
||||||
private readonly IDelegatingHandlerHandlerProviderFactory _factory;
|
|
||||||
private readonly ConcurrentDictionary<string, IDelegatingHandlerHandlerProvider> _housed;
|
|
||||||
|
|
||||||
public DelegatingHandlerHandlerHouse(IDelegatingHandlerHandlerProviderFactory factory)
|
|
||||||
{
|
|
||||||
_factory = factory;
|
|
||||||
_housed = new ConcurrentDictionary<string, IDelegatingHandlerHandlerProvider>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Response<IDelegatingHandlerHandlerProvider> Get(DownstreamReRoute request)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_housed.TryGetValue(request.ReRouteKey, out var provider))
|
|
||||||
{
|
|
||||||
//todo once day we might need a check here to see if we need to create a new provider
|
|
||||||
provider = _housed[request.ReRouteKey];
|
|
||||||
return new OkResponse<IDelegatingHandlerHandlerProvider>(provider);
|
|
||||||
}
|
|
||||||
|
|
||||||
//todo - unit test for this
|
|
||||||
var providerResponse = _factory.Get(request);
|
|
||||||
|
|
||||||
if (providerResponse.IsError)
|
|
||||||
{
|
|
||||||
return new ErrorResponse<IDelegatingHandlerHandlerProvider>(providerResponse.Errors);
|
|
||||||
}
|
|
||||||
|
|
||||||
provider = providerResponse.Data;
|
|
||||||
AddHoused(request.ReRouteKey, provider);
|
|
||||||
return new OkResponse<IDelegatingHandlerHandlerProvider>(provider);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
return new ErrorResponse<IDelegatingHandlerHandlerProvider>(new List<Error>()
|
|
||||||
{
|
|
||||||
new UnableToFindDelegatingHandlerProviderError($"unabe to find delegating handler provider for {request.ReRouteKey} exception is {ex}")
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddHoused(string key, IDelegatingHandlerHandlerProvider provider)
|
|
||||||
{
|
|
||||||
_housed.AddOrUpdate(key, provider, (k, v) => provider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace Ocelot.Requester
|
|
||||||
{
|
|
||||||
public class DelegatingHandlerHandlerProvider : IDelegatingHandlerHandlerProvider
|
|
||||||
{
|
|
||||||
private readonly Dictionary<int, Func<DelegatingHandler>> _handlers;
|
|
||||||
|
|
||||||
public DelegatingHandlerHandlerProvider()
|
|
||||||
{
|
|
||||||
_handlers = new Dictionary<int, Func<DelegatingHandler>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(Func<DelegatingHandler> handler)
|
|
||||||
{
|
|
||||||
var key = _handlers.Count == 0 ? 0 : _handlers.Count + 1;
|
|
||||||
_handlers[key] = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Func<DelegatingHandler>> Get()
|
|
||||||
{
|
|
||||||
return _handlers.Count > 0 ? _handlers.OrderBy(x => x.Key).Select(x => x.Value).ToList() : new List<Func<DelegatingHandler>>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Requester.QoS;
|
using Ocelot.Requester.QoS;
|
||||||
@ -7,38 +9,38 @@ using Ocelot.Responses;
|
|||||||
|
|
||||||
namespace Ocelot.Requester
|
namespace Ocelot.Requester
|
||||||
{
|
{
|
||||||
public class DelegatingHandlerHandlerProviderFactory : IDelegatingHandlerHandlerProviderFactory
|
public class DelegatingHandlerHandlerFactory : IDelegatingHandlerHandlerFactory
|
||||||
{
|
{
|
||||||
private readonly ITracingHandlerFactory _factory;
|
private readonly ITracingHandlerFactory _factory;
|
||||||
private readonly IOcelotLoggerFactory _loggerFactory;
|
private readonly IOcelotLoggerFactory _loggerFactory;
|
||||||
private readonly IDelegatingHandlerHandlerProvider _allRoutesProvider;
|
|
||||||
private readonly IQosProviderHouse _qosProviderHouse;
|
private readonly IQosProviderHouse _qosProviderHouse;
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
public DelegatingHandlerHandlerProviderFactory(IOcelotLoggerFactory loggerFactory,
|
public DelegatingHandlerHandlerFactory(IOcelotLoggerFactory loggerFactory,
|
||||||
IDelegatingHandlerHandlerProvider allRoutesProvider,
|
|
||||||
ITracingHandlerFactory factory,
|
ITracingHandlerFactory factory,
|
||||||
IQosProviderHouse qosProviderHouse)
|
IQosProviderHouse qosProviderHouse,
|
||||||
|
IServiceProvider serviceProvider)
|
||||||
{
|
{
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
_factory = factory;
|
_factory = factory;
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
_allRoutesProvider = allRoutesProvider;
|
|
||||||
_qosProviderHouse = qosProviderHouse;
|
_qosProviderHouse = qosProviderHouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Response<IDelegatingHandlerHandlerProvider> Get(DownstreamReRoute request)
|
public Response<List<Func<DelegatingHandler>>> Get(DownstreamReRoute request)
|
||||||
{
|
{
|
||||||
var handlersAppliedToAll = _allRoutesProvider.Get();
|
var handlersAppliedToAll = _serviceProvider.GetServices<DelegatingHandler>();
|
||||||
|
|
||||||
var provider = new DelegatingHandlerHandlerProvider();
|
var handlers = new List<Func<DelegatingHandler>>();
|
||||||
|
|
||||||
foreach (var handler in handlersAppliedToAll)
|
foreach (var handler in handlersAppliedToAll)
|
||||||
{
|
{
|
||||||
provider.Add(handler);
|
handlers.Add(() => handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.HttpHandlerOptions.UseTracing)
|
if (request.HttpHandlerOptions.UseTracing)
|
||||||
{
|
{
|
||||||
provider.Add(() => (DelegatingHandler)_factory.Get());
|
handlers.Add(() => (DelegatingHandler)_factory.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.IsQos)
|
if (request.IsQos)
|
||||||
@ -47,13 +49,13 @@ namespace Ocelot.Requester
|
|||||||
|
|
||||||
if (qosProvider.IsError)
|
if (qosProvider.IsError)
|
||||||
{
|
{
|
||||||
return new ErrorResponse<IDelegatingHandlerHandlerProvider>(qosProvider.Errors);
|
return new ErrorResponse<List<Func<DelegatingHandler>>>(qosProvider.Errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
provider.Add(() => new PollyCircuitBreakingDelegatingHandler(qosProvider.Data, _loggerFactory));
|
handlers.Add(() => new PollyCircuitBreakingDelegatingHandler(qosProvider.Data, _loggerFactory));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new OkResponse<IDelegatingHandlerHandlerProvider>(provider);
|
return new OkResponse<List<Func<DelegatingHandler>>>(handlers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,11 @@ namespace Ocelot.Requester
|
|||||||
{
|
{
|
||||||
public class HttpClientBuilder : IHttpClientBuilder
|
public class HttpClientBuilder : IHttpClientBuilder
|
||||||
{
|
{
|
||||||
private readonly IDelegatingHandlerHandlerHouse _house;
|
private readonly IDelegatingHandlerHandlerFactory _factory;
|
||||||
|
|
||||||
public HttpClientBuilder(IDelegatingHandlerHandlerHouse house)
|
public HttpClientBuilder(IDelegatingHandlerHandlerFactory house)
|
||||||
{
|
{
|
||||||
_house = house;
|
_factory = house;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IHttpClient Create(DownstreamReRoute request)
|
public IHttpClient Create(DownstreamReRoute request)
|
||||||
@ -24,11 +24,9 @@ namespace Ocelot.Requester
|
|||||||
|
|
||||||
private HttpMessageHandler CreateHttpMessageHandler(HttpMessageHandler httpMessageHandler, DownstreamReRoute request)
|
private HttpMessageHandler CreateHttpMessageHandler(HttpMessageHandler httpMessageHandler, DownstreamReRoute request)
|
||||||
{
|
{
|
||||||
var provider = _house.Get(request);
|
|
||||||
|
|
||||||
var handlers = provider.Data.Get();
|
|
||||||
|
|
||||||
//todo handle error
|
//todo handle error
|
||||||
|
var handlers = _factory.Get(request).Data;
|
||||||
|
|
||||||
handlers
|
handlers
|
||||||
.Select(handler => handler)
|
.Select(handler => handler)
|
||||||
.Reverse()
|
.Reverse()
|
||||||
|
@ -13,20 +13,20 @@ namespace Ocelot.Requester
|
|||||||
{
|
{
|
||||||
private readonly IHttpClientCache _cacheHandlers;
|
private readonly IHttpClientCache _cacheHandlers;
|
||||||
private readonly IOcelotLogger _logger;
|
private readonly IOcelotLogger _logger;
|
||||||
private readonly IDelegatingHandlerHandlerHouse _house;
|
private readonly IDelegatingHandlerHandlerFactory _factory;
|
||||||
|
|
||||||
public HttpClientHttpRequester(IOcelotLoggerFactory loggerFactory,
|
public HttpClientHttpRequester(IOcelotLoggerFactory loggerFactory,
|
||||||
IHttpClientCache cacheHandlers,
|
IHttpClientCache cacheHandlers,
|
||||||
IDelegatingHandlerHandlerHouse house)
|
IDelegatingHandlerHandlerFactory house)
|
||||||
{
|
{
|
||||||
_logger = loggerFactory.CreateLogger<HttpClientHttpRequester>();
|
_logger = loggerFactory.CreateLogger<HttpClientHttpRequester>();
|
||||||
_cacheHandlers = cacheHandlers;
|
_cacheHandlers = cacheHandlers;
|
||||||
_house = house;
|
_factory = house;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Response<HttpResponseMessage>> GetResponse(DownstreamContext request)
|
public async Task<Response<HttpResponseMessage>> GetResponse(DownstreamContext request)
|
||||||
{
|
{
|
||||||
var builder = new HttpClientBuilder(_house);
|
var builder = new HttpClientBuilder(_factory);
|
||||||
|
|
||||||
var cacheKey = GetCacheKey(request);
|
var cacheKey = GetCacheKey(request);
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
using Ocelot.Configuration;
|
|
||||||
using Ocelot.Responses;
|
|
||||||
|
|
||||||
namespace Ocelot.Requester
|
|
||||||
{
|
|
||||||
public interface IDelegatingHandlerHandlerHouse
|
|
||||||
{
|
|
||||||
Response<IDelegatingHandlerHandlerProvider> Get(DownstreamReRoute request);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net.Http;
|
|
||||||
|
|
||||||
namespace Ocelot.Requester
|
|
||||||
{
|
|
||||||
public interface IDelegatingHandlerHandlerProvider
|
|
||||||
{
|
|
||||||
void Add(Func<DelegatingHandler> handler);
|
|
||||||
List<Func<DelegatingHandler>> Get();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
|
|
||||||
namespace Ocelot.Requester
|
namespace Ocelot.Requester
|
||||||
{
|
{
|
||||||
public interface IDelegatingHandlerHandlerProviderFactory
|
public interface IDelegatingHandlerHandlerFactory
|
||||||
{
|
{
|
||||||
Response<IDelegatingHandlerHandlerProvider> Get(DownstreamReRoute request);
|
Response<List<Func<DelegatingHandler>>> Get(DownstreamReRoute request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ocelot.Values;
|
using Ocelot.Values;
|
||||||
|
|
||||||
@ -14,16 +13,16 @@ namespace Ocelot.ServiceDiscovery
|
|||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<List<Service>> Get()
|
public Task<List<Service>> Get()
|
||||||
{
|
{
|
||||||
return new List<Service>
|
return Task.FromResult(new List<Service>
|
||||||
{
|
{
|
||||||
new Service(_configuration.ServiceName,
|
new Service(_configuration.ServiceName,
|
||||||
new ServiceHostAndPort(_configuration.HostName, _configuration.Port),
|
new ServiceHostAndPort(_configuration.HostName, _configuration.Port),
|
||||||
"doesnt matter with service fabric",
|
"doesnt matter with service fabric",
|
||||||
"doesnt matter with service fabric",
|
"doesnt matter with service fabric",
|
||||||
new List<string>())
|
new List<string>())
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
116
test/Ocelot.AcceptanceTests/GzipTests.cs
Normal file
116
test/Ocelot.AcceptanceTests/GzipTests.cs
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text;
|
||||||
|
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 GzipTests : IDisposable
|
||||||
|
{
|
||||||
|
private IWebHost _builder;
|
||||||
|
private readonly Steps _steps;
|
||||||
|
|
||||||
|
public GzipTests()
|
||||||
|
{
|
||||||
|
_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 = 51879,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpstreamPathTemplate = "/",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Post" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var input = "people";
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879", "/", 200, "Hello from Laura", "\"people\""))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunning())
|
||||||
|
.And(x => _steps.GivenThePostHasGzipContent(input))
|
||||||
|
.When(x => _steps.WhenIPostUrlOnTheApiGateway("/"))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenThereIsAServiceRunningOn(string baseUrl, string basePath, int statusCode, string responseBody, string expected)
|
||||||
|
{
|
||||||
|
_builder = new WebHostBuilder()
|
||||||
|
.UseUrls(baseUrl)
|
||||||
|
.UseKestrel()
|
||||||
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
||||||
|
.UseIISIntegration()
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UsePathBase(basePath);
|
||||||
|
app.Run(async context =>
|
||||||
|
{
|
||||||
|
if(context.Request.Headers.TryGetValue("Content-Encoding", out var contentEncoding))
|
||||||
|
{
|
||||||
|
contentEncoding.First().ShouldBe("gzip");
|
||||||
|
|
||||||
|
string text = null;
|
||||||
|
using (var decompress = new GZipStream(context.Request.Body, CompressionMode.Decompress))
|
||||||
|
{
|
||||||
|
using (var sr = new StreamReader(decompress)) {
|
||||||
|
text = sr.ReadToEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(text != expected)
|
||||||
|
{
|
||||||
|
throw new Exception("not gzipped");
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Response.StatusCode = statusCode;
|
||||||
|
await context.Response.WriteAsync(responseBody);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Response.StatusCode = statusCode;
|
||||||
|
await context.Response.WriteAsync("downstream path didnt match base path");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
_builder.Start();
|
||||||
|
}
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_builder?.Dispose();
|
||||||
|
_steps.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,6 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
private IWebHost _builder;
|
private IWebHost _builder;
|
||||||
private readonly Steps _steps;
|
private readonly Steps _steps;
|
||||||
private string _downstreamPath;
|
|
||||||
|
|
||||||
public HeaderTests()
|
public HeaderTests()
|
||||||
{
|
{
|
||||||
@ -221,13 +220,15 @@ namespace Ocelot.AcceptanceTests
|
|||||||
.Configure(app =>
|
.Configure(app =>
|
||||||
{
|
{
|
||||||
app.UsePathBase(basePath);
|
app.UsePathBase(basePath);
|
||||||
app.Run(async context =>
|
app.Run(context =>
|
||||||
{
|
{
|
||||||
context.Response.OnStarting(() => {
|
context.Response.OnStarting(() => {
|
||||||
context.Response.Headers.Add(headerKey, headerValue);
|
context.Response.Headers.Add(headerKey, headerValue);
|
||||||
context.Response.StatusCode = statusCode;
|
context.Response.StatusCode = statusCode;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
@ -235,11 +236,6 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_builder.Start();
|
_builder.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void ThenTheDownstreamUrlPathShouldBe(string expectedDownstreamPath)
|
|
||||||
{
|
|
||||||
_downstreamPath.ShouldBe(expectedDownstreamPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_builder?.Dispose();
|
_builder?.Dispose();
|
||||||
|
@ -26,8 +26,9 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_steps = new Steps();
|
_steps = new Steps();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_call_handlers()
|
public void should_call_di_handlers()
|
||||||
{
|
{
|
||||||
var configuration = new FileConfiguration
|
var configuration = new FileConfiguration
|
||||||
{
|
{
|
||||||
@ -42,7 +43,7 @@ namespace Ocelot.AcceptanceTests
|
|||||||
new FileHostAndPort
|
new FileHostAndPort
|
||||||
{
|
{
|
||||||
Host = "localhost",
|
Host = "localhost",
|
||||||
Port = 61879,
|
Port = 7187,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UpstreamPathTemplate = "/",
|
UpstreamPathTemplate = "/",
|
||||||
@ -51,27 +52,98 @@ namespace Ocelot.AcceptanceTests
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var handlerOne = new FakeHandler();
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:7187", "/", 200, "Hello from Laura"))
|
||||||
var handlerTwo = new FakeHandler();
|
|
||||||
|
|
||||||
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:61879", "/", 200, "Hello from Laura"))
|
|
||||||
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
.And(x => _steps.GivenOcelotIsRunningWithHandlers(handlerOne, handlerTwo))
|
.And(x => _steps.GivenOcelotIsRunningWithHandlersRegisteredInDi<FakeHandler, FakeHandlerTwo>())
|
||||||
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||||
.And(x => ThenTheHandlersAreCalledCorrectly(handlerOne, handlerTwo))
|
.And(x => ThenTheHandlersAreCalledCorrectly())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheHandlersAreCalledCorrectly(FakeHandler one, FakeHandler two)
|
|
||||||
|
[Fact]
|
||||||
|
public void should_call_di_handlers_with_dependency()
|
||||||
{
|
{
|
||||||
one.TimeCalled.ShouldBeLessThan(two.TimeCalled);
|
var configuration = new FileConfiguration
|
||||||
|
{
|
||||||
|
ReRoutes = new List<FileReRoute>
|
||||||
|
{
|
||||||
|
new FileReRoute
|
||||||
|
{
|
||||||
|
DownstreamPathTemplate = "/",
|
||||||
|
DownstreamScheme = "http",
|
||||||
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
||||||
|
{
|
||||||
|
new FileHostAndPort
|
||||||
|
{
|
||||||
|
Host = "localhost",
|
||||||
|
Port = 7188,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpstreamPathTemplate = "/",
|
||||||
|
UpstreamHttpMethod = new List<string> { "Get" },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var dependency = new FakeDependency();
|
||||||
|
|
||||||
|
this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:7188", "/", 200, "Hello from Laura"))
|
||||||
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
||||||
|
.And(x => _steps.GivenOcelotIsRunningWithHandlersRegisteredInDi<FakeHandlerWithDependency>(dependency))
|
||||||
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
|
||||||
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
||||||
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
||||||
|
.And(x => ThenTheDependencyIsCalled(dependency))
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheDependencyIsCalled(FakeDependency dependency)
|
||||||
|
{
|
||||||
|
dependency.Called.ShouldBeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheHandlersAreCalledCorrectly()
|
||||||
|
{
|
||||||
|
FakeHandler.TimeCalled.ShouldBeLessThan(FakeHandlerTwo.TimeCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FakeDependency
|
||||||
|
{
|
||||||
|
public bool Called;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeHandlerWithDependency : DelegatingHandler
|
||||||
|
{
|
||||||
|
private FakeDependency _dependency;
|
||||||
|
|
||||||
|
public FakeHandlerWithDependency(FakeDependency dependency)
|
||||||
|
{
|
||||||
|
_dependency = dependency;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_dependency.Called = true;
|
||||||
|
return await base.SendAsync(request, cancellationToken);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FakeHandler : DelegatingHandler
|
class FakeHandler : DelegatingHandler
|
||||||
{
|
{
|
||||||
public DateTime TimeCalled { get; private set; }
|
public static DateTime TimeCalled { get; private set; }
|
||||||
|
|
||||||
|
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
TimeCalled = DateTime.Now;
|
||||||
|
return await base.SendAsync(request, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class FakeHandlerTwo : DelegatingHandler
|
||||||
|
{
|
||||||
|
public static DateTime TimeCalled { get; private set; }
|
||||||
|
|
||||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,9 @@ using Ocelot.Middleware;
|
|||||||
using Shouldly;
|
using Shouldly;
|
||||||
using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
|
using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
|
||||||
using Ocelot.AcceptanceTests.Caching;
|
using Ocelot.AcceptanceTests.Caching;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Text;
|
||||||
|
using static Ocelot.AcceptanceTests.HttpDelegatingHandlersTests;
|
||||||
|
|
||||||
namespace Ocelot.AcceptanceTests
|
namespace Ocelot.AcceptanceTests
|
||||||
{
|
{
|
||||||
@ -172,10 +175,9 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_ocelotClient = _ocelotServer.CreateClient();
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public void GivenOcelotIsRunningWithHandlersRegisteredInDi<TOne, TWo>()
|
||||||
/// 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.
|
where TOne : DelegatingHandler
|
||||||
/// </summary>
|
where TWo : DelegatingHandler
|
||||||
public void GivenOcelotIsRunningWithHandlers(DelegatingHandler handlerOne, DelegatingHandler handlerTwo)
|
|
||||||
{
|
{
|
||||||
_webHostBuilder = new WebHostBuilder();
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
@ -193,8 +195,40 @@ namespace Ocelot.AcceptanceTests
|
|||||||
{
|
{
|
||||||
s.AddSingleton(_webHostBuilder);
|
s.AddSingleton(_webHostBuilder);
|
||||||
s.AddOcelot()
|
s.AddOcelot()
|
||||||
.AddDelegatingHandler(() => handlerOne)
|
.AddDelegatingHandler<TOne>()
|
||||||
.AddDelegatingHandler(() => handlerTwo);
|
.AddDelegatingHandler<TWo>();
|
||||||
|
})
|
||||||
|
.Configure(a =>
|
||||||
|
{
|
||||||
|
a.UseOcelot().Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder);
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenOcelotIsRunningWithHandlersRegisteredInDi<TOne>(FakeDependency dependency)
|
||||||
|
where TOne : DelegatingHandler
|
||||||
|
{
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
|
_webHostBuilder
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddSingleton(_webHostBuilder);
|
||||||
|
s.AddSingleton<FakeDependency>(dependency);
|
||||||
|
s.AddOcelot()
|
||||||
|
.AddDelegatingHandler<TOne>();
|
||||||
})
|
})
|
||||||
.Configure(a =>
|
.Configure(a =>
|
||||||
{
|
{
|
||||||
@ -582,6 +616,22 @@ namespace Ocelot.AcceptanceTests
|
|||||||
_postContent = new StringContent(postcontent);
|
_postContent = new StringContent(postcontent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void GivenThePostHasGzipContent(object input)
|
||||||
|
{
|
||||||
|
string json = JsonConvert.SerializeObject(input);
|
||||||
|
byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true))
|
||||||
|
{
|
||||||
|
gzip.Write(jsonBytes, 0, jsonBytes.Length);
|
||||||
|
}
|
||||||
|
ms.Position = 0;
|
||||||
|
StreamContent content = new StreamContent(ms);
|
||||||
|
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||||
|
content.Headers.ContentEncoding.Add("gzip");
|
||||||
|
_postContent = content;
|
||||||
|
}
|
||||||
|
|
||||||
public void ThenTheResponseBodyShouldBe(string expectedBody)
|
public void ThenTheResponseBodyShouldBe(string expectedBody)
|
||||||
{
|
{
|
||||||
_response.Content.ReadAsStringAsync().Result.ShouldBe(expectedBody);
|
_response.Content.ReadAsStringAsync().Result.ShouldBe(expectedBody);
|
||||||
|
722
test/Ocelot.AcceptanceTests/Steps.cs.orig
Normal file
722
test/Ocelot.AcceptanceTests/Steps.cs.orig
Normal file
@ -0,0 +1,722 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using CacheManager.Core;
|
||||||
|
using IdentityServer4.AccessTokenValidation;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.TestHost;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Ocelot.Configuration.File;
|
||||||
|
using Ocelot.DependencyInjection;
|
||||||
|
using Ocelot.Middleware;
|
||||||
|
using Shouldly;
|
||||||
|
using ConfigurationBuilder = Microsoft.Extensions.Configuration.ConfigurationBuilder;
|
||||||
|
using Ocelot.AcceptanceTests.Caching;
|
||||||
|
<<<<<<< HEAD
|
||||||
|
using static Ocelot.AcceptanceTests.HttpDelegatingHandlersTests;
|
||||||
|
||||||| merged common ancestors
|
||||||
|
=======
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Text;
|
||||||
|
>>>>>>> develop
|
||||||
|
|
||||||
|
namespace Ocelot.AcceptanceTests
|
||||||
|
{
|
||||||
|
public class Steps : IDisposable
|
||||||
|
{
|
||||||
|
private TestServer _ocelotServer;
|
||||||
|
private HttpClient _ocelotClient;
|
||||||
|
private HttpResponseMessage _response;
|
||||||
|
private HttpContent _postContent;
|
||||||
|
private BearerToken _token;
|
||||||
|
public HttpClient OcelotClient => _ocelotClient;
|
||||||
|
public string RequestIdKey = "OcRequestId";
|
||||||
|
private readonly Random _random;
|
||||||
|
private IWebHostBuilder _webHostBuilder;
|
||||||
|
|
||||||
|
public Steps()
|
||||||
|
{
|
||||||
|
_random = new Random();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenThereIsAConfiguration(FileConfiguration fileConfiguration)
|
||||||
|
{
|
||||||
|
var configurationPath = TestConfiguration.ConfigurationPath;
|
||||||
|
|
||||||
|
var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
|
||||||
|
|
||||||
|
if (File.Exists(configurationPath))
|
||||||
|
{
|
||||||
|
File.Delete(configurationPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllText(configurationPath, jsonConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenThereIsAConfiguration(FileConfiguration fileConfiguration, string configurationPath)
|
||||||
|
{
|
||||||
|
var jsonConfiguration = JsonConvert.SerializeObject(fileConfiguration);
|
||||||
|
|
||||||
|
if (File.Exists(configurationPath))
|
||||||
|
{
|
||||||
|
File.Delete(configurationPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllText(configurationPath, jsonConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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()
|
||||||
|
{
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
|
_webHostBuilder
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddOcelot();
|
||||||
|
})
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseOcelot().Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder);
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void GivenOcelotIsRunningUsingButterfly(string butterflyUrl)
|
||||||
|
{
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
|
_webHostBuilder
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddOcelot()
|
||||||
|
.AddOpenTracing(option =>
|
||||||
|
{
|
||||||
|
//this is the url that the butterfly collector server is running on...
|
||||||
|
option.CollectorUrl = butterflyUrl;
|
||||||
|
option.Service = "Ocelot";
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.Use(async (context, next) =>
|
||||||
|
{
|
||||||
|
await next.Invoke();
|
||||||
|
});
|
||||||
|
app.UseOcelot().Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder);
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public void GivenIHaveAddedXForwardedForHeader(string value)
|
||||||
|
{
|
||||||
|
_ocelotClient.DefaultRequestHeaders.TryAddWithoutValidation("X-Forwarded-For", value);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public void GivenOcelotIsRunningWithMiddleareBeforePipeline<T>(Func<object, Task> callback)
|
||||||
|
{
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
|
_webHostBuilder
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddOcelot();
|
||||||
|
})
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseMiddleware<T>(callback);
|
||||||
|
app.UseOcelot().Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder);
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenOcelotIsRunningWithHandlersRegisteredInDi<TOne, TWo>()
|
||||||
|
where TOne : DelegatingHandler
|
||||||
|
where TWo : DelegatingHandler
|
||||||
|
{
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
|
_webHostBuilder
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddSingleton(_webHostBuilder);
|
||||||
|
s.AddOcelot()
|
||||||
|
.AddDelegatingHandler<TOne>()
|
||||||
|
.AddDelegatingHandler<TWo>();
|
||||||
|
})
|
||||||
|
.Configure(a =>
|
||||||
|
{
|
||||||
|
a.UseOcelot().Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder);
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenOcelotIsRunningWithHandlersRegisteredInDi<TOne>(FakeDependency dependency)
|
||||||
|
where TOne : DelegatingHandler
|
||||||
|
{
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
|
_webHostBuilder
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddSingleton(_webHostBuilder);
|
||||||
|
s.AddSingleton<FakeDependency>(dependency);
|
||||||
|
s.AddOcelot()
|
||||||
|
.AddDelegatingHandler<TOne>();
|
||||||
|
})
|
||||||
|
.Configure(a =>
|
||||||
|
{
|
||||||
|
a.UseOcelot().Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder);
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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(Action<IdentityServerAuthenticationOptions> options, string authenticationProviderKey)
|
||||||
|
{
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
|
_webHostBuilder
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddOcelot();
|
||||||
|
s.AddAuthentication()
|
||||||
|
.AddIdentityServerAuthentication(authenticationProviderKey, options);
|
||||||
|
})
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseOcelot().Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder);
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ThenTheResponseHeaderIs(string key, string value)
|
||||||
|
{
|
||||||
|
var header = _response.Headers.GetValues(key);
|
||||||
|
header.First().ShouldBe(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenOcelotIsRunningUsingJsonSerializedCache()
|
||||||
|
{
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
|
_webHostBuilder
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddOcelot()
|
||||||
|
.AddCacheManager((x) =>
|
||||||
|
{
|
||||||
|
x.WithMicrosoftLogging(log =>
|
||||||
|
{
|
||||||
|
log.AddConsole(LogLevel.Debug);
|
||||||
|
})
|
||||||
|
.WithJsonSerializer()
|
||||||
|
.WithHandle(typeof(InMemoryJsonHandle<>));
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseOcelot().Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder);
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenOcelotIsRunningUsingConsulToStoreConfig()
|
||||||
|
{
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
|
_webHostBuilder
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddOcelot().AddStoreOcelotConfigurationInConsul();
|
||||||
|
})
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseOcelot().Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder);
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenOcelotIsRunningUsingConsulToStoreConfigAndJsonSerializedCache()
|
||||||
|
{
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
|
||||||
|
_webHostBuilder
|
||||||
|
.ConfigureAppConfiguration((hostingContext, config) =>
|
||||||
|
{
|
||||||
|
config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath);
|
||||||
|
var env = hostingContext.HostingEnvironment;
|
||||||
|
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
|
||||||
|
config.AddJsonFile("configuration.json");
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
})
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddOcelot()
|
||||||
|
.AddCacheManager((x) =>
|
||||||
|
{
|
||||||
|
x.WithMicrosoftLogging(log =>
|
||||||
|
{
|
||||||
|
log.AddConsole(LogLevel.Debug);
|
||||||
|
})
|
||||||
|
.WithJsonSerializer()
|
||||||
|
.WithHandle(typeof(InMemoryJsonHandle<>));
|
||||||
|
})
|
||||||
|
.AddStoreOcelotConfigurationInConsul();
|
||||||
|
})
|
||||||
|
.Configure(app =>
|
||||||
|
{
|
||||||
|
app.UseOcelot().Wait();
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder);
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void ThenTheResponseShouldBe(FileConfiguration expecteds)
|
||||||
|
{
|
||||||
|
var response = JsonConvert.DeserializeObject<FileConfiguration>(_response.Content.ReadAsStringAsync().Result);
|
||||||
|
|
||||||
|
response.GlobalConfiguration.RequestIdKey.ShouldBe(expecteds.GlobalConfiguration.RequestIdKey);
|
||||||
|
response.GlobalConfiguration.ServiceDiscoveryProvider.Host.ShouldBe(expecteds.GlobalConfiguration.ServiceDiscoveryProvider.Host);
|
||||||
|
response.GlobalConfiguration.ServiceDiscoveryProvider.Port.ShouldBe(expecteds.GlobalConfiguration.ServiceDiscoveryProvider.Port);
|
||||||
|
|
||||||
|
for (var i = 0; i < response.ReRoutes.Count; i++)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < response.ReRoutes[i].DownstreamHostAndPorts.Count; j++)
|
||||||
|
{
|
||||||
|
var result = response.ReRoutes[i].DownstreamHostAndPorts[j];
|
||||||
|
var expected = expecteds.ReRoutes[i].DownstreamHostAndPorts[j];
|
||||||
|
result.Host.ShouldBe(expected.Host);
|
||||||
|
result.Port.ShouldBe(expected.Port);
|
||||||
|
}
|
||||||
|
|
||||||
|
response.ReRoutes[i].DownstreamPathTemplate.ShouldBe(expecteds.ReRoutes[i].DownstreamPathTemplate);
|
||||||
|
response.ReRoutes[i].DownstreamScheme.ShouldBe(expecteds.ReRoutes[i].DownstreamScheme);
|
||||||
|
response.ReRoutes[i].UpstreamPathTemplate.ShouldBe(expecteds.ReRoutes[i].UpstreamPathTemplate);
|
||||||
|
response.ReRoutes[i].UpstreamHttpMethod.ShouldBe(expecteds.ReRoutes[i].UpstreamHttpMethod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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(OcelotPipelineConfiguration ocelotPipelineConfig)
|
||||||
|
{
|
||||||
|
var builder = new ConfigurationBuilder()
|
||||||
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
|
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
|
||||||
|
.AddJsonFile("configuration.json")
|
||||||
|
.AddEnvironmentVariables();
|
||||||
|
|
||||||
|
var configuration = builder.Build();
|
||||||
|
_webHostBuilder = new WebHostBuilder();
|
||||||
|
_webHostBuilder.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
s.AddSingleton(_webHostBuilder);
|
||||||
|
});
|
||||||
|
|
||||||
|
_ocelotServer = new TestServer(_webHostBuilder
|
||||||
|
.UseConfiguration(configuration)
|
||||||
|
.ConfigureServices(s =>
|
||||||
|
{
|
||||||
|
Action<ConfigurationBuilderCachePart> settings = (x) =>
|
||||||
|
{
|
||||||
|
x.WithMicrosoftLogging(log =>
|
||||||
|
{
|
||||||
|
log.AddConsole(LogLevel.Debug);
|
||||||
|
})
|
||||||
|
.WithDictionaryHandle();
|
||||||
|
};
|
||||||
|
|
||||||
|
s.AddOcelot(configuration);
|
||||||
|
})
|
||||||
|
.ConfigureLogging(l =>
|
||||||
|
{
|
||||||
|
l.AddConsole();
|
||||||
|
l.AddDebug();
|
||||||
|
})
|
||||||
|
.Configure(a =>
|
||||||
|
{
|
||||||
|
a.UseOcelot(ocelotPipelineConfig).Wait();
|
||||||
|
}));
|
||||||
|
|
||||||
|
_ocelotClient = _ocelotServer.CreateClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenIHaveAddedATokenToMyRequest()
|
||||||
|
{
|
||||||
|
_ocelotClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token.AccessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenIHaveAToken(string url)
|
||||||
|
{
|
||||||
|
var tokenUrl = $"{url}/connect/token";
|
||||||
|
var formData = new List<KeyValuePair<string, string>>
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, string>("client_id", "client"),
|
||||||
|
new KeyValuePair<string, string>("client_secret", "secret"),
|
||||||
|
new KeyValuePair<string, string>("scope", "api"),
|
||||||
|
new KeyValuePair<string, string>("username", "test"),
|
||||||
|
new KeyValuePair<string, string>("password", "test"),
|
||||||
|
new KeyValuePair<string, string>("grant_type", "password")
|
||||||
|
};
|
||||||
|
var content = new FormUrlEncodedContent(formData);
|
||||||
|
|
||||||
|
using (var httpClient = new HttpClient())
|
||||||
|
{
|
||||||
|
var response = httpClient.PostAsync(tokenUrl, content).Result;
|
||||||
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenIHaveATokenForApiReadOnlyScope(string url)
|
||||||
|
{
|
||||||
|
var tokenUrl = $"{url}/connect/token";
|
||||||
|
var formData = new List<KeyValuePair<string, string>>
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, string>("client_id", "client"),
|
||||||
|
new KeyValuePair<string, string>("client_secret", "secret"),
|
||||||
|
new KeyValuePair<string, string>("scope", "api.readOnly"),
|
||||||
|
new KeyValuePair<string, string>("username", "test"),
|
||||||
|
new KeyValuePair<string, string>("password", "test"),
|
||||||
|
new KeyValuePair<string, string>("grant_type", "password")
|
||||||
|
};
|
||||||
|
var content = new FormUrlEncodedContent(formData);
|
||||||
|
|
||||||
|
using (var httpClient = new HttpClient())
|
||||||
|
{
|
||||||
|
var response = httpClient.PostAsync(tokenUrl, content).Result;
|
||||||
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenIHaveATokenForApi2(string url)
|
||||||
|
{
|
||||||
|
var tokenUrl = $"{url}/connect/token";
|
||||||
|
var formData = new List<KeyValuePair<string, string>>
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, string>("client_id", "client"),
|
||||||
|
new KeyValuePair<string, string>("client_secret", "secret"),
|
||||||
|
new KeyValuePair<string, string>("scope", "api2"),
|
||||||
|
new KeyValuePair<string, string>("username", "test"),
|
||||||
|
new KeyValuePair<string, string>("password", "test"),
|
||||||
|
new KeyValuePair<string, string>("grant_type", "password")
|
||||||
|
};
|
||||||
|
var content = new FormUrlEncodedContent(formData);
|
||||||
|
|
||||||
|
using (var httpClient = new HttpClient())
|
||||||
|
{
|
||||||
|
var response = httpClient.PostAsync(tokenUrl, content).Result;
|
||||||
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenIHaveAnOcelotToken(string adminPath)
|
||||||
|
{
|
||||||
|
var tokenUrl = $"{adminPath}/connect/token";
|
||||||
|
var formData = new List<KeyValuePair<string, string>>
|
||||||
|
{
|
||||||
|
new KeyValuePair<string, string>("client_id", "admin"),
|
||||||
|
new KeyValuePair<string, string>("client_secret", "secret"),
|
||||||
|
new KeyValuePair<string, string>("scope", "admin"),
|
||||||
|
new KeyValuePair<string, string>("username", "admin"),
|
||||||
|
new KeyValuePair<string, string>("password", "admin"),
|
||||||
|
new KeyValuePair<string, string>("grant_type", "password")
|
||||||
|
};
|
||||||
|
var content = new FormUrlEncodedContent(formData);
|
||||||
|
|
||||||
|
var response = _ocelotClient.PostAsync(tokenUrl, content).Result;
|
||||||
|
var responseContent = response.Content.ReadAsStringAsync().Result;
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
_token = JsonConvert.DeserializeObject<BearerToken>(responseContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void VerifyIdentiryServerStarted(string url)
|
||||||
|
{
|
||||||
|
using (var httpClient = new HttpClient())
|
||||||
|
{
|
||||||
|
var response = httpClient.GetAsync($"{url}/.well-known/openid-configuration").Result;
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WhenIGetUrlOnTheApiGateway(string url)
|
||||||
|
{
|
||||||
|
_response = _ocelotClient.GetAsync(url).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenIAddAHeader(string key, string value)
|
||||||
|
{
|
||||||
|
_ocelotClient.DefaultRequestHeaders.Add(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WhenIGetUrlOnTheApiGatewayMultipleTimes(string url, int times)
|
||||||
|
{
|
||||||
|
var tasks = new Task[times];
|
||||||
|
|
||||||
|
for (int i = 0; i < times; i++)
|
||||||
|
{
|
||||||
|
var urlCopy = url;
|
||||||
|
tasks[i] = GetForServiceDiscoveryTest(urlCopy);
|
||||||
|
Thread.Sleep(_random.Next(40, 60));
|
||||||
|
}
|
||||||
|
|
||||||
|
Task.WaitAll(tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task GetForServiceDiscoveryTest(string url)
|
||||||
|
{
|
||||||
|
var response = await _ocelotClient.GetAsync(url);
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
int count = int.Parse(content);
|
||||||
|
count.ShouldBeGreaterThan(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WhenIGetUrlOnTheApiGatewayMultipleTimesForRateLimit(string url, int times)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < times; i++)
|
||||||
|
{
|
||||||
|
var clientId = "ocelotclient1";
|
||||||
|
var request = new HttpRequestMessage(new HttpMethod("GET"), url);
|
||||||
|
request.Headers.Add("ClientId", clientId);
|
||||||
|
_response = _ocelotClient.SendAsync(request).Result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WhenIGetUrlOnTheApiGateway(string url, string requestId)
|
||||||
|
{
|
||||||
|
_ocelotClient.DefaultRequestHeaders.TryAddWithoutValidation(RequestIdKey, requestId);
|
||||||
|
|
||||||
|
_response = _ocelotClient.GetAsync(url).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WhenIPostUrlOnTheApiGateway(string url)
|
||||||
|
{
|
||||||
|
_response = _ocelotClient.PostAsync(url, _postContent).Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenThePostHasContent(string postcontent)
|
||||||
|
{
|
||||||
|
_postContent = new StringContent(postcontent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GivenThePostHasGzipContent(object input)
|
||||||
|
{
|
||||||
|
string json = JsonConvert.SerializeObject(input);
|
||||||
|
byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
|
||||||
|
MemoryStream ms = new MemoryStream();
|
||||||
|
using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true))
|
||||||
|
{
|
||||||
|
gzip.Write(jsonBytes, 0, jsonBytes.Length);
|
||||||
|
}
|
||||||
|
ms.Position = 0;
|
||||||
|
StreamContent content = new StreamContent(ms);
|
||||||
|
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
|
||||||
|
content.Headers.ContentEncoding.Add("gzip");
|
||||||
|
_postContent = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ThenTheResponseBodyShouldBe(string expectedBody)
|
||||||
|
{
|
||||||
|
_response.Content.ReadAsStringAsync().Result.ShouldBe(expectedBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ThenTheStatusCodeShouldBe(HttpStatusCode expectedHttpStatusCode)
|
||||||
|
{
|
||||||
|
_response.StatusCode.ShouldBe(expectedHttpStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ThenTheStatusCodeShouldBe(int expectedHttpStatusCode)
|
||||||
|
{
|
||||||
|
var responseStatusCode = (int)_response.StatusCode;
|
||||||
|
responseStatusCode.ShouldBe(expectedHttpStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_ocelotClient?.Dispose();
|
||||||
|
_ocelotServer?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ThenTheRequestIdIsReturned()
|
||||||
|
{
|
||||||
|
_response.Headers.GetValues(RequestIdKey).First().ShouldNotBeNullOrEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ThenTheRequestIdIsReturned(string expected)
|
||||||
|
{
|
||||||
|
_response.Headers.GetValues(RequestIdKey).First().ShouldBe(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ThenTheContentLengthIs(int expected)
|
||||||
|
{
|
||||||
|
_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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
<VersionPrefix>0.0.0-dev</VersionPrefix>
|
||||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||||
@ -11,23 +10,19 @@
|
|||||||
<RuntimeIdentifiers>osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64</RuntimeIdentifiers>
|
<RuntimeIdentifiers>osx.10.11-x64;osx.10.12-x64;win7-x64;win10-x64</RuntimeIdentifiers>
|
||||||
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>..\..\codeanalysis.ruleset</CodeAnalysisRuleSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="Views;Areas\**\Views">
|
<None Update="Views;Areas\**\Views">
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="configuration.json;appsettings.json;idsrv3test.pfx">
|
<None Update="configuration.json;appsettings.json;idsrv3test.pfx">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj"/>
|
<ProjectReference Include="..\..\src\Ocelot\Ocelot.csproj"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0"/>
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0"/>
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0"/>
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0"/>
|
||||||
@ -43,5 +38,4 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
@ -6,6 +6,7 @@ namespace Ocelot.UnitTests.Authentication
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Authentication.Middleware;
|
using Ocelot.Authentication.Middleware;
|
||||||
@ -44,10 +45,11 @@ namespace Ocelot.UnitTests.Authentication
|
|||||||
|
|
||||||
private void WhenICallTheMiddleware()
|
private void WhenICallTheMiddleware()
|
||||||
{
|
{
|
||||||
_next = async (context) => {
|
_next = (context) => {
|
||||||
byte[] byteArray = Encoding.ASCII.GetBytes("The user is authenticated");
|
byte[] byteArray = Encoding.ASCII.GetBytes("The user is authenticated");
|
||||||
MemoryStream stream = new MemoryStream(byteArray);
|
var stream = new MemoryStream(byteArray);
|
||||||
context.HttpContext.Response.Body = stream;
|
context.HttpContext.Response.Body = stream;
|
||||||
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
_middleware = new AuthenticationMiddleware(_next, _factory.Object);
|
_middleware = new AuthenticationMiddleware(_next, _factory.Object);
|
||||||
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
_middleware.Invoke(_downstreamContext).GetAwaiter().GetResult();
|
||||||
@ -55,10 +57,11 @@ namespace Ocelot.UnitTests.Authentication
|
|||||||
|
|
||||||
private void GivenTheTestServerPipelineIsConfigured()
|
private void GivenTheTestServerPipelineIsConfigured()
|
||||||
{
|
{
|
||||||
_next = async (context) => {
|
_next = (context) => {
|
||||||
byte[] byteArray = Encoding.ASCII.GetBytes("The user is authenticated");
|
byte[] byteArray = Encoding.ASCII.GetBytes("The user is authenticated");
|
||||||
MemoryStream stream = new MemoryStream(byteArray);
|
var stream = new MemoryStream(byteArray);
|
||||||
context.HttpContext.Response.Body = stream;
|
context.HttpContext.Response.Body = stream;
|
||||||
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,18 +4,17 @@ namespace Ocelot.UnitTests.Authorization
|
|||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Authorisation;
|
using Ocelot.Authorisation;
|
||||||
using Ocelot.Authorisation.Middleware;
|
using Ocelot.Authorisation.Middleware;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
|
|
||||||
public class AuthorisationMiddlewareTests
|
public class AuthorisationMiddlewareTests
|
||||||
@ -36,9 +35,7 @@ namespace Ocelot.UnitTests.Authorization
|
|||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
|
||||||
_next = async context => {
|
_next = context => Task.CompletedTask;
|
||||||
//do nothing
|
|
||||||
};
|
|
||||||
_middleware = new AuthorisationMiddleware(_next, _authService.Object, _authScopesService.Object, _loggerFactory.Object);
|
_middleware = new AuthorisationMiddleware(_next, _authService.Object, _authScopesService.Object, _loggerFactory.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
using Shouldly;
|
using Shouldly;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Cache;
|
using Ocelot.Cache;
|
||||||
using Ocelot.Cache.Middleware;
|
using Ocelot.Cache.Middleware;
|
||||||
@ -43,9 +44,7 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
_cacheManager = new OcelotCacheManagerCache<CachedResponse>(cacheManagerOutputCache);
|
_cacheManager = new OcelotCacheManagerCache<CachedResponse>(cacheManagerOutputCache);
|
||||||
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
_downstreamContext = new DownstreamContext(new DefaultHttpContext());
|
||||||
_downstreamContext.DownstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123");
|
_downstreamContext.DownstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123");
|
||||||
_next = async context => {
|
_next = context => Task.CompletedTask;
|
||||||
//do nothing..
|
|
||||||
};
|
|
||||||
_middleware = new OutputCacheMiddleware(_next, _loggerFactory.Object, _cacheManager, _regionCreator);
|
_middleware = new OutputCacheMiddleware(_next, _loggerFactory.Object, _cacheManager, _regionCreator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,19 +7,16 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Cache;
|
using Ocelot.Cache;
|
||||||
using Ocelot.Cache.Middleware;
|
using Ocelot.Cache.Middleware;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
using Ocelot.DownstreamRouteFinder;
|
||||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Responses;
|
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
@ -42,10 +39,7 @@ namespace Ocelot.UnitTests.Cache
|
|||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<OutputCacheMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<OutputCacheMiddleware>()).Returns(_logger.Object);
|
||||||
_next = async context => {
|
_next = context => Task.CompletedTask;
|
||||||
//do nothing
|
|
||||||
};
|
|
||||||
|
|
||||||
_downstreamContext.DownstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123");
|
_downstreamContext.DownstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://some.url/blah?abcd=123");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace Ocelot.UnitTests.Claims
|
namespace Ocelot.UnitTests.Claims
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Claims;
|
using Ocelot.Claims;
|
||||||
@ -32,9 +33,7 @@ namespace Ocelot.UnitTests.Claims
|
|||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<ClaimsBuilderMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<ClaimsBuilderMiddleware>()).Returns(_logger.Object);
|
||||||
_next = async context => {
|
_next = context => Task.CompletedTask;
|
||||||
//do nothing
|
|
||||||
};
|
|
||||||
_middleware = new ClaimsBuilderMiddleware(_next, _loggerFactory.Object, _addHeaders.Object);
|
_middleware = new ClaimsBuilderMiddleware(_next, _loggerFactory.Object, _addHeaders.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,15 +41,13 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
private Exception _ex;
|
private Exception _ex;
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_add_delegating_handlers()
|
public void should_add_delegating_handlers_with_di()
|
||||||
{
|
{
|
||||||
var fakeOne = new FakeDelegatingHandler(0);
|
|
||||||
var fakeTwo = new FakeDelegatingHandler(1);
|
|
||||||
|
|
||||||
this.Given(x => WhenISetUpOcelotServices())
|
this.Given(x => WhenISetUpOcelotServices())
|
||||||
.When(x => AddDelegate(fakeOne))
|
.When(x => AddDelegate<FakeDelegatingHandler>())
|
||||||
.And(x => AddDelegate(fakeTwo))
|
.And(x => AddDelegate<FakeDelegatingHandlerTwo>())
|
||||||
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers())
|
.Then(x => ThenTheProviderIsRegisteredAndReturnsHandlers<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,15 +162,12 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
path.Path.ShouldBe("/administration");
|
path.Path.ShouldBe("/administration");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenTheProviderIsRegisteredAndReturnsHandlers()
|
private void ThenTheProviderIsRegisteredAndReturnsHandlers<TOne, TWo>()
|
||||||
{
|
{
|
||||||
_serviceProvider = _services.BuildServiceProvider();
|
_serviceProvider = _services.BuildServiceProvider();
|
||||||
var provider = _serviceProvider.GetService<IDelegatingHandlerHandlerProvider>();
|
var handlers = _serviceProvider.GetServices<DelegatingHandler>().ToList();
|
||||||
var handlers = provider.Get();
|
handlers[0].ShouldBeOfType<TOne>();
|
||||||
var handler = (FakeDelegatingHandler)handlers[0].Invoke();
|
handlers[1].ShouldBeOfType<TWo>();
|
||||||
handler.Order.ShouldBe(0);
|
|
||||||
handler = (FakeDelegatingHandler)handlers[1].Invoke();
|
|
||||||
handler.Order.ShouldBe(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnlyOneVersionOfEachCacheIsRegistered()
|
private void OnlyOneVersionOfEachCacheIsRegistered()
|
||||||
@ -213,9 +208,9 @@ namespace Ocelot.UnitTests.DependencyInjection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddDelegate(DelegatingHandler handler)
|
private void AddDelegate<T>() where T : DelegatingHandler
|
||||||
{
|
{
|
||||||
_ocelotBuilder.AddDelegatingHandler(() => handler);
|
_ocelotBuilder.AddDelegatingHandler<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenAnOcelotBuilderIsReturned()
|
private void ThenAnOcelotBuilderIsReturned()
|
||||||
|
@ -4,9 +4,8 @@ using Ocelot.Middleware.Multiplexer;
|
|||||||
namespace Ocelot.UnitTests.DownstreamRouteFinder
|
namespace Ocelot.UnitTests.DownstreamRouteFinder
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
@ -42,9 +41,7 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder
|
|||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<DownstreamRouteFinderMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<DownstreamRouteFinderMiddleware>()).Returns(_logger.Object);
|
||||||
_next = async context => {
|
_next = context => Task.CompletedTask;
|
||||||
//do nothing
|
|
||||||
};
|
|
||||||
_multiplexer = new Mock<IMultiplexer>();
|
_multiplexer = new Mock<IMultiplexer>();
|
||||||
_middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _finder.Object, _provider.Object, _multiplexer.Object);
|
_middleware = new DownstreamRouteFinderMiddleware(_next, _loggerFactory.Object, _finder.Object, _provider.Object, _multiplexer.Object);
|
||||||
}
|
}
|
||||||
|
@ -6,23 +6,19 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
using Ocelot.DownstreamRouteFinder;
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.DownstreamUrlCreator;
|
|
||||||
using Ocelot.DownstreamUrlCreator.Middleware;
|
using Ocelot.DownstreamUrlCreator.Middleware;
|
||||||
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
|
using Ocelot.DownstreamUrlCreator.UrlTemplateReplacer;
|
||||||
using Ocelot.Infrastructure.RequestData;
|
|
||||||
using Ocelot.Logging;
|
using Ocelot.Logging;
|
||||||
using Ocelot.Responses;
|
using Ocelot.Responses;
|
||||||
using Ocelot.Values;
|
using Ocelot.Values;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
public class DownstreamUrlCreatorMiddlewareTests
|
public class DownstreamUrlCreatorMiddlewareTests
|
||||||
@ -43,9 +39,7 @@ namespace Ocelot.UnitTests.DownstreamUrlCreator
|
|||||||
_loggerFactory.Setup(x => x.CreateLogger<DownstreamUrlCreatorMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<DownstreamUrlCreatorMiddleware>()).Returns(_logger.Object);
|
||||||
_downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamPathPlaceholderReplacer>();
|
_downstreamUrlTemplateVariableReplacer = new Mock<IDownstreamPathPlaceholderReplacer>();
|
||||||
_downstreamContext.DownstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://my.url/abc/?q=123");
|
_downstreamContext.DownstreamRequest = new HttpRequestMessage(HttpMethod.Get, "https://my.url/abc/?q=123");
|
||||||
_next = async context => {
|
_next = context => Task.CompletedTask;
|
||||||
//do nothing
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -11,11 +11,12 @@ using Ocelot.Configuration.Builder;
|
|||||||
using Ocelot.Headers;
|
using Ocelot.Headers;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Ocelot.Authorisation.Middleware;
|
using Ocelot.Authorisation.Middleware;
|
||||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
|
||||||
using Ocelot.Middleware;
|
using Ocelot.Middleware;
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Headers
|
namespace Ocelot.UnitTests.Headers
|
||||||
{
|
{
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
public class HttpHeadersTransformationMiddlewareTests
|
public class HttpHeadersTransformationMiddlewareTests
|
||||||
{
|
{
|
||||||
private Mock<IHttpContextRequestHeaderReplacer> _preReplacer;
|
private Mock<IHttpContextRequestHeaderReplacer> _preReplacer;
|
||||||
@ -34,9 +35,7 @@ namespace Ocelot.UnitTests.Headers
|
|||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<AuthorisationMiddleware>()).Returns(_logger.Object);
|
||||||
_next = async context => {
|
_next = context => Task.CompletedTask;
|
||||||
//do nothing
|
|
||||||
};
|
|
||||||
_middleware = new HttpHeadersTransformationMiddleware(_next, _loggerFactory.Object, _preReplacer.Object, _postReplacer.Object);
|
_middleware = new HttpHeadersTransformationMiddleware(_next, _loggerFactory.Object, _preReplacer.Object, _postReplacer.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,14 +4,12 @@ namespace Ocelot.UnitTests.Headers
|
|||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.AspNetCore.Builder;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
using Ocelot.DownstreamRouteFinder;
|
||||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
|
||||||
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
using Ocelot.DownstreamRouteFinder.UrlMatcher;
|
||||||
using Ocelot.Headers;
|
using Ocelot.Headers;
|
||||||
using Ocelot.Headers.Middleware;
|
using Ocelot.Headers.Middleware;
|
||||||
@ -37,9 +35,7 @@ namespace Ocelot.UnitTests.Headers
|
|||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<HttpRequestHeadersBuilderMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<HttpRequestHeadersBuilderMiddleware>()).Returns(_logger.Object);
|
||||||
_next = async context => {
|
_next = context => Task.CompletedTask;
|
||||||
//do nothing
|
|
||||||
};
|
|
||||||
_middleware = new HttpRequestHeadersBuilderMiddleware(_next, _loggerFactory.Object, _addHeaders.Object);
|
_middleware = new HttpRequestHeadersBuilderMiddleware(_next, _loggerFactory.Object, _addHeaders.Object);
|
||||||
_downstreamContext.DownstreamRequest = new HttpRequestMessage();
|
_downstreamContext.DownstreamRequest = new HttpRequestMessage();
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,13 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
private readonly LoadBalancerHouse _loadBalancerHouse;
|
private readonly LoadBalancerHouse _loadBalancerHouse;
|
||||||
private Response<ILoadBalancer> _getResult;
|
private Response<ILoadBalancer> _getResult;
|
||||||
private readonly Mock<ILoadBalancerFactory> _factory;
|
private readonly Mock<ILoadBalancerFactory> _factory;
|
||||||
private ServiceProviderConfiguration _serviceProviderConfig;
|
private readonly ServiceProviderConfiguration _serviceProviderConfig;
|
||||||
|
|
||||||
public LoadBalancerHouseTests()
|
public LoadBalancerHouseTests()
|
||||||
{
|
{
|
||||||
_factory = new Mock<ILoadBalancerFactory>();
|
_factory = new Mock<ILoadBalancerFactory>();
|
||||||
_loadBalancerHouse = new LoadBalancerHouse(_factory.Object);
|
_loadBalancerHouse = new LoadBalancerHouse(_factory.Object);
|
||||||
|
_serviceProviderConfig = new ServiceProviderConfiguration("myType","myHost",123);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -4,6 +4,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
@ -43,9 +44,7 @@ namespace Ocelot.UnitTests.LoadBalancer
|
|||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<LoadBalancingMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<LoadBalancingMiddleware>()).Returns(_logger.Object);
|
||||||
_next = async context => {
|
_next = context => Task.CompletedTask;
|
||||||
//do nothing
|
|
||||||
};
|
|
||||||
_downstreamContext.DownstreamRequest = _downstreamRequest;
|
_downstreamContext.DownstreamRequest = _downstreamRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ namespace Ocelot.UnitTests.Middleware
|
|||||||
{
|
{
|
||||||
_aggregator = new Mock<IResponseAggregator>();
|
_aggregator = new Mock<IResponseAggregator>();
|
||||||
_context = new DownstreamContext(new DefaultHttpContext());
|
_context = new DownstreamContext(new DefaultHttpContext());
|
||||||
_pipeline = async context => { _count++; };
|
_pipeline = context => Task.FromResult(_count++);
|
||||||
_multiplexer = new Multiplexer(_aggregator.Object);
|
_multiplexer = new Multiplexer(_aggregator.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ namespace Ocelot.UnitTests.QueryStrings
|
|||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
@ -17,9 +16,8 @@ namespace Ocelot.UnitTests.QueryStrings
|
|||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
public class QueryStringBuilderMiddlewareTests
|
public class QueryStringBuilderMiddlewareTests
|
||||||
{
|
{
|
||||||
@ -36,9 +34,7 @@ namespace Ocelot.UnitTests.QueryStrings
|
|||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<QueryStringBuilderMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<QueryStringBuilderMiddleware>()).Returns(_logger.Object);
|
||||||
_next = async context => {
|
_next = context => Task.CompletedTask;
|
||||||
//do nothing
|
|
||||||
};
|
|
||||||
_addQueries = new Mock<IAddQueriesToRequest>();
|
_addQueries = new Mock<IAddQueriesToRequest>();
|
||||||
_downstreamContext.DownstreamRequest = new HttpRequestMessage();
|
_downstreamContext.DownstreamRequest = new HttpRequestMessage();
|
||||||
_middleware = new QueryStringBuilderMiddleware(_next, _loggerFactory.Object, _addQueries.Object);
|
_middleware = new QueryStringBuilderMiddleware(_next, _loggerFactory.Object, _addQueries.Object);
|
||||||
|
@ -15,9 +15,9 @@ namespace Ocelot.UnitTests.RateLimit
|
|||||||
using Shouldly;
|
using Shouldly;
|
||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Ocelot.DownstreamRouteFinder.Middleware;
|
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
public class ClientRateLimitMiddlewareTests
|
public class ClientRateLimitMiddlewareTests
|
||||||
{
|
{
|
||||||
@ -42,8 +42,7 @@ namespace Ocelot.UnitTests.RateLimit
|
|||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<ClientRateLimitMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<ClientRateLimitMiddleware>()).Returns(_logger.Object);
|
||||||
_next = async (context) => {
|
_next = context => Task.CompletedTask;
|
||||||
};
|
|
||||||
_middleware = new ClientRateLimitMiddleware(_next, _loggerFactory.Object, _rateLimitCounterHandler);
|
_middleware = new ClientRateLimitMiddleware(_next, _loggerFactory.Object, _rateLimitCounterHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
public class RequestMapperTests
|
public class RequestMapperTests
|
||||||
{
|
{
|
||||||
@ -118,19 +119,151 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Should_map_content_type_header()
|
public void Should_handle_no_content()
|
||||||
{
|
{
|
||||||
|
this.Given(_ => GivenTheInputRequestHasNoContent())
|
||||||
|
.And(_ => GivenTheInputRequestHasMethod("GET"))
|
||||||
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
||||||
|
.When(_ => WhenMapped())
|
||||||
|
.Then(_ => ThenNoErrorIsReturned())
|
||||||
|
.And(_ => ThenTheMappedRequestHasNoContent())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Should_map_content_headers()
|
||||||
|
{
|
||||||
|
byte[] md5bytes = new byte[0];
|
||||||
|
using (var md5 = MD5.Create())
|
||||||
|
{
|
||||||
|
md5bytes = md5.ComputeHash(Encoding.UTF8.GetBytes("some md5"));
|
||||||
|
}
|
||||||
|
|
||||||
this.Given(_ => GivenTheInputRequestHasContent("This is my content"))
|
this.Given(_ => GivenTheInputRequestHasContent("This is my content"))
|
||||||
.And(_ => GivenTheContentTypeIs("application/json"))
|
.And(_ => GivenTheContentTypeIs("application/json"))
|
||||||
|
.And(_ => GivenTheContentEncodingIs("gzip, compress"))
|
||||||
|
.And(_ => GivenTheContentLanguageIs("english"))
|
||||||
|
.And(_ => GivenTheContentLocationIs("/my-receipts/38"))
|
||||||
|
.And(_ => GivenTheContentRangeIs("bytes 1-2/*"))
|
||||||
|
.And(_ => GivenTheContentDispositionIs("inline"))
|
||||||
|
.And(_ => GivenTheContentMD5Is(md5bytes))
|
||||||
.And(_ => GivenTheInputRequestHasMethod("GET"))
|
.And(_ => GivenTheInputRequestHasMethod("GET"))
|
||||||
.And(_ => GivenTheInputRequestHasAValidUri())
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
||||||
.When(_ => WhenMapped())
|
.When(_ => WhenMapped())
|
||||||
.Then(_ => ThenNoErrorIsReturned())
|
.Then(_ => ThenNoErrorIsReturned())
|
||||||
.And(_ => ThenTheMappedRequestHasContentTypeHeader("application/json"))
|
.And(_ => ThenTheMappedRequestHasContentTypeHeader("application/json"))
|
||||||
|
.And(_ => ThenTheMappedRequestHasContentEncodingHeader("gzip", "compress"))
|
||||||
|
.And(_ => ThenTheMappedRequestHasContentLanguageHeader("english"))
|
||||||
|
.And(_ => ThenTheMappedRequestHasContentLocationHeader("/my-receipts/38"))
|
||||||
|
.And(_ => ThenTheMappedRequestHasContentMD5Header(md5bytes))
|
||||||
|
.And(_ => ThenTheMappedRequestHasContentRangeHeader())
|
||||||
|
.And(_ => ThenTheMappedRequestHasContentDispositionHeader("inline"))
|
||||||
.And(_ => ThenTheMappedRequestHasContentSize("This is my content".Length))
|
.And(_ => ThenTheMappedRequestHasContentSize("This is my content".Length))
|
||||||
|
.And(_ => ThenTheContentHeadersAreNotAddedToNonContentHeaders())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void should_not_add_content_headers()
|
||||||
|
{
|
||||||
|
this.Given(_ => GivenTheInputRequestHasContent("This is my content"))
|
||||||
|
.And(_ => GivenTheContentTypeIs("application/json"))
|
||||||
|
.And(_ => GivenTheInputRequestHasMethod("POST"))
|
||||||
|
.And(_ => GivenTheInputRequestHasAValidUri())
|
||||||
|
.When(_ => WhenMapped())
|
||||||
|
.Then(_ => ThenNoErrorIsReturned())
|
||||||
|
.And(_ => ThenTheMappedRequestHasContentTypeHeader("application/json"))
|
||||||
|
.And(_ => ThenTheMappedRequestHasContentSize("This is my content".Length))
|
||||||
|
.And(_ => ThenTheOtherContentTypeHeadersAreNotMapped())
|
||||||
|
.BDDfy();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheContentHeadersAreNotAddedToNonContentHeaders()
|
||||||
|
{
|
||||||
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-Disposition");
|
||||||
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-ContentMD5");
|
||||||
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-ContentRange");
|
||||||
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-ContentLanguage");
|
||||||
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-ContentEncoding");
|
||||||
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-ContentLocation");
|
||||||
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-Length");
|
||||||
|
_mappedRequest.Data.Headers.ShouldNotContain(x => x.Key == "Content-Type");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheOtherContentTypeHeadersAreNotMapped()
|
||||||
|
{
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentDisposition.ShouldBeNull();
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentMD5.ShouldBeNull();
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentRange.ShouldBeNull();
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentLanguage.ShouldBeEmpty();
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentEncoding.ShouldBeEmpty();
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentLocation.ShouldBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheMappedRequestHasContentDispositionHeader(string expected)
|
||||||
|
{
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentDisposition.DispositionType.ShouldBe(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheContentDispositionIs(string input)
|
||||||
|
{
|
||||||
|
_inputRequest.Headers.Add("Content-Disposition", input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheMappedRequestHasContentMD5Header(byte[] expected)
|
||||||
|
{
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentMD5.ShouldBe(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheContentMD5Is(byte[] input)
|
||||||
|
{
|
||||||
|
var base64 = Convert.ToBase64String(input);
|
||||||
|
_inputRequest.Headers.Add("Content-MD5", base64);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheMappedRequestHasContentRangeHeader()
|
||||||
|
{
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentRange.From.ShouldBe(1);
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentRange.To.ShouldBe(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheContentRangeIs(string input)
|
||||||
|
{
|
||||||
|
_inputRequest.Headers.Add("Content-Range", input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheMappedRequestHasContentLocationHeader(string expected)
|
||||||
|
{
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentLocation.OriginalString.ShouldBe(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheContentLocationIs(string input)
|
||||||
|
{
|
||||||
|
_inputRequest.Headers.Add("Content-Location", input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheMappedRequestHasContentLanguageHeader(string expected)
|
||||||
|
{
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentLanguage.First().ShouldBe(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheContentLanguageIs(string input)
|
||||||
|
{
|
||||||
|
_inputRequest.Headers.Add("Content-Language", input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ThenTheMappedRequestHasContentEncodingHeader(string expected, string expectedTwo)
|
||||||
|
{
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentEncoding.ToArray()[0].ShouldBe(expected);
|
||||||
|
_mappedRequest.Data.Content.Headers.ContentEncoding.ToArray()[1].ShouldBe(expectedTwo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheContentEncodingIs(string input)
|
||||||
|
{
|
||||||
|
_inputRequest.Headers.Add("Content-Encoding", input);
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenTheContentTypeIs(string contentType)
|
private void GivenTheContentTypeIs(string contentType)
|
||||||
{
|
{
|
||||||
_inputRequest.ContentType = contentType;
|
_inputRequest.ContentType = contentType;
|
||||||
@ -146,18 +279,6 @@
|
|||||||
_mappedRequest.Data.Content.Headers.ContentLength.ShouldBe(expected);
|
_mappedRequest.Data.Content.Headers.ContentLength.ShouldBe(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Should_handle_no_content()
|
|
||||||
{
|
|
||||||
this.Given(_ => GivenTheInputRequestHasNoContent())
|
|
||||||
.And(_ => GivenTheInputRequestHasMethod("GET"))
|
|
||||||
.And(_ => GivenTheInputRequestHasAValidUri())
|
|
||||||
.When(_ => WhenMapped())
|
|
||||||
.Then(_ => ThenNoErrorIsReturned())
|
|
||||||
.And(_ => ThenTheMappedRequestHasNoContent())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheInputRequestHasMethod(string method)
|
private void GivenTheInputRequestHasMethod(string method)
|
||||||
{
|
{
|
||||||
_inputRequest.Method = method;
|
_inputRequest.Method = method;
|
||||||
|
@ -9,6 +9,7 @@ namespace Ocelot.UnitTests.RequestId
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
using Ocelot.DownstreamRouteFinder;
|
using Ocelot.DownstreamRouteFinder;
|
||||||
@ -40,8 +41,10 @@ namespace Ocelot.UnitTests.RequestId
|
|||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<ReRouteRequestIdMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<ReRouteRequestIdMiddleware>()).Returns(_logger.Object);
|
||||||
_next = async context => {
|
_next = context =>
|
||||||
|
{
|
||||||
context.HttpContext.Response.Headers.Add("LSRequestId", context.HttpContext.TraceIdentifier);
|
context.HttpContext.Response.Headers.Add("LSRequestId", context.HttpContext.TraceIdentifier);
|
||||||
|
return Task.CompletedTask;
|
||||||
};
|
};
|
||||||
_middleware = new ReRouteRequestIdMiddleware(_next, _loggerFactory.Object, _repo.Object);
|
_middleware = new ReRouteRequestIdMiddleware(_next, _loggerFactory.Object, _repo.Object);
|
||||||
_downstreamContext.DownstreamRequest = _downstreamRequest;
|
_downstreamContext.DownstreamRequest = _downstreamRequest;
|
||||||
|
@ -1,137 +0,0 @@
|
|||||||
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;
|
|
||||||
using TestStack.BDDfy;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Requester
|
|
||||||
{
|
|
||||||
public class DelegatingHandlerHandlerHouseTests
|
|
||||||
{
|
|
||||||
private readonly DelegatingHandlerHandlerHouse _house;
|
|
||||||
private Mock<IDelegatingHandlerHandlerProviderFactory> _factory;
|
|
||||||
private readonly Mock<IDelegatingHandlerHandlerProvider> _provider;
|
|
||||||
private DownstreamReRoute _request;
|
|
||||||
private Response<IDelegatingHandlerHandlerProvider> _result;
|
|
||||||
|
|
||||||
public DelegatingHandlerHandlerHouseTests()
|
|
||||||
{
|
|
||||||
_provider = new Mock<IDelegatingHandlerHandlerProvider>();
|
|
||||||
_factory = new Mock<IDelegatingHandlerHandlerProviderFactory>();
|
|
||||||
_house = new DelegatingHandlerHandlerHouse(_factory.Object);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_create_and_store_provider()
|
|
||||||
{
|
|
||||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("key").Build();
|
|
||||||
|
|
||||||
this.Given(x => GivenTheRequest(reRoute))
|
|
||||||
.And(x => GivenTheProviderReturns())
|
|
||||||
.When(x => WhenIGet())
|
|
||||||
.Then(x => ThenTheFactoryIsCalled(1))
|
|
||||||
.And(x => ThenTheProviderIsNotNull())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_get_provider()
|
|
||||||
{
|
|
||||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("key").Build();
|
|
||||||
|
|
||||||
this.Given(x => GivenTheRequest(reRoute))
|
|
||||||
.And(x => GivenTheProviderReturns())
|
|
||||||
.And(x => WhenIGet())
|
|
||||||
.And(x => GivenTheFactoryIsCleared())
|
|
||||||
.When(x => WhenIGet())
|
|
||||||
.Then(x => ThenTheFactoryIsCalled(0))
|
|
||||||
.And(x => ThenTheProviderIsNotNull())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_return_error()
|
|
||||||
{
|
|
||||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("key").Build();
|
|
||||||
|
|
||||||
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();
|
|
||||||
_result.Errors[0].ShouldBeOfType<UnableToFindDelegatingHandlerProviderError>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheProviderThrows()
|
|
||||||
{
|
|
||||||
_factory.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Throws<Exception>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheFactoryIsCleared()
|
|
||||||
{
|
|
||||||
_factory = new Mock<IDelegatingHandlerHandlerProviderFactory>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenTheProviderIsNotNull()
|
|
||||||
{
|
|
||||||
_result.Data.ShouldBe(_provider.Object);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WhenIGet()
|
|
||||||
{
|
|
||||||
_result = _house.Get(_request);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheRequest(DownstreamReRoute request)
|
|
||||||
{
|
|
||||||
_request = request;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheProviderReturns()
|
|
||||||
{
|
|
||||||
_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)
|
|
||||||
{
|
|
||||||
_factory.Verify(x => x.Get(_request), Times.Exactly(times));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.Configuration;
|
using Ocelot.Configuration;
|
||||||
using Ocelot.Configuration.Builder;
|
using Ocelot.Configuration.Builder;
|
||||||
@ -17,45 +18,30 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
{
|
{
|
||||||
public class DelegatingHandlerHandlerProviderFactoryTests
|
public class DelegatingHandlerHandlerProviderFactoryTests
|
||||||
{
|
{
|
||||||
private readonly DelegatingHandlerHandlerProviderFactory _factory;
|
private DelegatingHandlerHandlerFactory _factory;
|
||||||
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
private Mock<IOcelotLoggerFactory> _loggerFactory;
|
||||||
private DownstreamReRoute _request;
|
private DownstreamReRoute _request;
|
||||||
private Response<IDelegatingHandlerHandlerProvider> _provider;
|
private Response<List<Func<DelegatingHandler>>> _provider;
|
||||||
private readonly Mock<IDelegatingHandlerHandlerProvider> _allRoutesProvider;
|
|
||||||
private readonly Mock<IQosProviderHouse> _qosProviderHouse;
|
private readonly Mock<IQosProviderHouse> _qosProviderHouse;
|
||||||
private readonly Mock<ITracingHandlerFactory> _tracingFactory;
|
private readonly Mock<ITracingHandlerFactory> _tracingFactory;
|
||||||
|
private IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
public DelegatingHandlerHandlerProviderFactoryTests()
|
public DelegatingHandlerHandlerProviderFactoryTests()
|
||||||
{
|
{
|
||||||
_tracingFactory = new Mock<ITracingHandlerFactory>();
|
_tracingFactory = new Mock<ITracingHandlerFactory>();
|
||||||
_qosProviderHouse = new Mock<IQosProviderHouse>();
|
_qosProviderHouse = new Mock<IQosProviderHouse>();
|
||||||
_allRoutesProvider = new Mock<IDelegatingHandlerHandlerProvider>();
|
|
||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_factory = new DelegatingHandlerHandlerProviderFactory(_loggerFactory.Object, _allRoutesProvider.Object, _tracingFactory.Object, _qosProviderHouse.Object);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheQosProviderHouseReturns(Response<IQoSProvider> qosProvider)
|
|
||||||
{
|
|
||||||
_qosProviderHouse
|
|
||||||
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
|
|
||||||
.Returns(qosProvider);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_all_from_all_routes_provider_and_qos()
|
public void should_all_from_all_routes_provider_and_qos()
|
||||||
{
|
{
|
||||||
var handlers = new List<Func<DelegatingHandler>>
|
|
||||||
{
|
|
||||||
() => new FakeDelegatingHandler(0),
|
|
||||||
() => new FakeDelegatingHandler(1)
|
|
||||||
};
|
|
||||||
|
|
||||||
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
var reRoute = new DownstreamReRouteBuilder().WithIsQos(true)
|
||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
|
||||||
|
|
||||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||||
.And(x => GivenTheAllRoutesProviderReturns(handlers))
|
.And(x => GivenTheServiceProviderReturns<FakeDelegatingHandler, FakeDelegatingHandlerTwo>())
|
||||||
.When(x => WhenIGet())
|
.When(x => WhenIGet())
|
||||||
.Then(x => ThenThereIsDelegatesInProvider(3))
|
.Then(x => ThenThereIsDelegatesInProvider(3))
|
||||||
.And(x => ThenTheDelegatesAreAddedCorrectly())
|
.And(x => ThenTheDelegatesAreAddedCorrectly())
|
||||||
@ -70,7 +56,7 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
|
.WithHttpHandlerOptions(new HttpHandlerOptions(true, true, false)).WithReRouteKey("").Build();
|
||||||
|
|
||||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
.And(x => GivenTheAllRoutesProviderReturns())
|
.And(x => GivenTheServiceProviderReturnsNothing())
|
||||||
.When(x => WhenIGet())
|
.When(x => WhenIGet())
|
||||||
.Then(x => ThenNoDelegatesAreInTheProvider())
|
.Then(x => ThenNoDelegatesAreInTheProvider())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -84,7 +70,7 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
|
|
||||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
.And(x => GivenTheQosProviderHouseReturns(new OkResponse<IQoSProvider>(It.IsAny<PollyQoSProvider>())))
|
||||||
.And(x => GivenTheAllRoutesProviderReturns())
|
.And(x => GivenTheServiceProviderReturnsNothing())
|
||||||
.When(x => WhenIGet())
|
.When(x => WhenIGet())
|
||||||
.Then(x => ThenThereIsDelegatesInProvider(1))
|
.Then(x => ThenThereIsDelegatesInProvider(1))
|
||||||
.And(x => ThenItIsPolly(0))
|
.And(x => ThenItIsPolly(0))
|
||||||
@ -99,12 +85,28 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
|
|
||||||
this.Given(x => GivenTheFollowingRequest(reRoute))
|
this.Given(x => GivenTheFollowingRequest(reRoute))
|
||||||
.And(x => GivenTheQosProviderHouseReturns(new ErrorResponse<IQoSProvider>(It.IsAny<Error>())))
|
.And(x => GivenTheQosProviderHouseReturns(new ErrorResponse<IQoSProvider>(It.IsAny<Error>())))
|
||||||
.And(x => GivenTheAllRoutesProviderReturns())
|
.And(x => GivenTheServiceProviderReturnsNothing())
|
||||||
.When(x => WhenIGet())
|
.When(x => WhenIGet())
|
||||||
.Then(x => ThenAnErrorIsReturned())
|
.Then(x => ThenAnErrorIsReturned())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void GivenTheServiceProviderReturns<TOne, TTwo>()
|
||||||
|
where TOne : DelegatingHandler
|
||||||
|
where TTwo : DelegatingHandler
|
||||||
|
{
|
||||||
|
IServiceCollection services = new ServiceCollection();
|
||||||
|
services.AddSingleton<DelegatingHandler, TOne>();
|
||||||
|
services.AddSingleton<DelegatingHandler, TTwo>();
|
||||||
|
_serviceProvider = services.BuildServiceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenTheServiceProviderReturnsNothing()
|
||||||
|
{
|
||||||
|
IServiceCollection services = new ServiceCollection();
|
||||||
|
_serviceProvider = services.BuildServiceProvider();
|
||||||
|
}
|
||||||
|
|
||||||
private void ThenAnErrorIsReturned()
|
private void ThenAnErrorIsReturned()
|
||||||
{
|
{
|
||||||
_provider.IsError.ShouldBeTrue();
|
_provider.IsError.ShouldBeTrue();
|
||||||
@ -112,29 +114,27 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
|
|
||||||
private void ThenTheDelegatesAreAddedCorrectly()
|
private void ThenTheDelegatesAreAddedCorrectly()
|
||||||
{
|
{
|
||||||
var delegates = _provider.Data.Get();
|
var delegates = _provider.Data;
|
||||||
|
|
||||||
var del = delegates[0].Invoke();
|
var del = delegates[0].Invoke();
|
||||||
var handler = (FakeDelegatingHandler) del;
|
var handler = (FakeDelegatingHandler) del;
|
||||||
handler.Order.ShouldBe(0);
|
handler.Order.ShouldBe(1);
|
||||||
|
|
||||||
del = delegates[1].Invoke();
|
del = delegates[1].Invoke();
|
||||||
handler = (FakeDelegatingHandler)del;
|
var handlerTwo = (FakeDelegatingHandlerTwo) del;
|
||||||
handler.Order.ShouldBe(1);
|
handlerTwo.Order.ShouldBe(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheAllRoutesProviderReturns()
|
private void GivenTheQosProviderHouseReturns(Response<IQoSProvider> qosProvider)
|
||||||
{
|
{
|
||||||
_allRoutesProvider.Setup(x => x.Get()).Returns(new List<Func<DelegatingHandler>>());
|
_qosProviderHouse
|
||||||
}
|
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
|
||||||
|
.Returns(qosProvider);
|
||||||
private void GivenTheAllRoutesProviderReturns(List<Func<DelegatingHandler>> handlers)
|
|
||||||
{
|
|
||||||
_allRoutesProvider.Setup(x => x.Get()).Returns(handlers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenItIsPolly(int i)
|
private void ThenItIsPolly(int i)
|
||||||
{
|
{
|
||||||
var delegates = _provider.Data.Get();
|
var delegates = _provider.Data;
|
||||||
var del = delegates[i].Invoke();
|
var del = delegates[i].Invoke();
|
||||||
del.ShouldBeOfType<PollyCircuitBreakingDelegatingHandler>();
|
del.ShouldBeOfType<PollyCircuitBreakingDelegatingHandler>();
|
||||||
}
|
}
|
||||||
@ -142,7 +142,7 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
private void ThenThereIsDelegatesInProvider(int count)
|
private void ThenThereIsDelegatesInProvider(int count)
|
||||||
{
|
{
|
||||||
_provider.ShouldNotBeNull();
|
_provider.ShouldNotBeNull();
|
||||||
_provider.Data.Get().Count.ShouldBe(count);
|
_provider.Data.Count.ShouldBe(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheFollowingRequest(DownstreamReRoute request)
|
private void GivenTheFollowingRequest(DownstreamReRoute request)
|
||||||
@ -152,13 +152,14 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
|
|
||||||
private void WhenIGet()
|
private void WhenIGet()
|
||||||
{
|
{
|
||||||
|
_factory = new DelegatingHandlerHandlerFactory(_loggerFactory.Object, _tracingFactory.Object, _qosProviderHouse.Object, _serviceProvider);
|
||||||
_provider = _factory.Get(_request);
|
_provider = _factory.Get(_request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ThenNoDelegatesAreInTheProvider()
|
private void ThenNoDelegatesAreInTheProvider()
|
||||||
{
|
{
|
||||||
_provider.ShouldNotBeNull();
|
_provider.ShouldNotBeNull();
|
||||||
_provider.Data.Get().Count.ShouldBe(0);
|
_provider.Data.Count.ShouldBe(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Net.Http;
|
|
||||||
using Ocelot.Requester;
|
|
||||||
using Shouldly;
|
|
||||||
using TestStack.BDDfy;
|
|
||||||
using Xunit;
|
|
||||||
|
|
||||||
namespace Ocelot.UnitTests.Requester
|
|
||||||
{
|
|
||||||
public class DelegatingHandlerHandlerProviderTests
|
|
||||||
{
|
|
||||||
private readonly DelegatingHandlerHandlerProvider _provider;
|
|
||||||
private List<Func<DelegatingHandler>> _handlers;
|
|
||||||
|
|
||||||
public DelegatingHandlerHandlerProviderTests()
|
|
||||||
{
|
|
||||||
_provider = new DelegatingHandlerHandlerProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_return_empty_list()
|
|
||||||
{
|
|
||||||
this.When(x => WhenIGet())
|
|
||||||
.Then(x => ThenAnEmptyListIsReturned())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void should_get_delegating_handlers_in_order_first_in_first_out()
|
|
||||||
{
|
|
||||||
this.Given(x => GivenTheHandlers())
|
|
||||||
.When(x => WhenIGet())
|
|
||||||
.Then(x => ThenTheHandlersAreReturnedInOrder())
|
|
||||||
.BDDfy();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenAnEmptyListIsReturned()
|
|
||||||
{
|
|
||||||
_handlers.Count.ShouldBe(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenTheHandlersAreReturnedInOrder()
|
|
||||||
{
|
|
||||||
var handler = (FakeDelegatingHandler)_handlers[0].Invoke();
|
|
||||||
handler.Order.ShouldBe(0);
|
|
||||||
handler = (FakeDelegatingHandler)_handlers[1].Invoke();
|
|
||||||
handler.Order.ShouldBe(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WhenIGet()
|
|
||||||
{
|
|
||||||
_handlers = _provider.Get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GivenTheHandlers()
|
|
||||||
{
|
|
||||||
_provider.Add(() => new FakeDelegatingHandler(0));
|
|
||||||
_provider.Add(() => new FakeDelegatingHandler(1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -9,6 +9,7 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
{
|
{
|
||||||
public FakeDelegatingHandler()
|
public FakeDelegatingHandler()
|
||||||
{
|
{
|
||||||
|
Order = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FakeDelegatingHandler(int order)
|
public FakeDelegatingHandler(int order)
|
||||||
@ -16,6 +17,24 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
Order = order;
|
Order = order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int Order {get;private set;}
|
||||||
|
|
||||||
|
public DateTime TimeCalled {get;private set;}
|
||||||
|
|
||||||
|
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
TimeCalled = DateTime.Now;
|
||||||
|
return Task.FromResult(new HttpResponseMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FakeDelegatingHandlerTwo : DelegatingHandler
|
||||||
|
{
|
||||||
|
public FakeDelegatingHandlerTwo()
|
||||||
|
{
|
||||||
|
Order = 2;
|
||||||
|
}
|
||||||
|
|
||||||
public int Order {get;private set;}
|
public int Order {get;private set;}
|
||||||
public DateTime TimeCalled {get;private set;}
|
public DateTime TimeCalled {get;private set;}
|
||||||
|
|
||||||
|
@ -15,25 +15,22 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
public class HttpClientBuilderTests
|
public class HttpClientBuilderTests
|
||||||
{
|
{
|
||||||
private readonly HttpClientBuilder _builder;
|
private readonly HttpClientBuilder _builder;
|
||||||
private readonly Mock<IDelegatingHandlerHandlerHouse> _house;
|
private readonly Mock<IDelegatingHandlerHandlerFactory> _factory;
|
||||||
private readonly Mock<IDelegatingHandlerHandlerProvider> _provider;
|
|
||||||
private IHttpClient _httpClient;
|
private IHttpClient _httpClient;
|
||||||
private HttpResponseMessage _response;
|
private HttpResponseMessage _response;
|
||||||
private DownstreamReRoute _request;
|
private DownstreamReRoute _request;
|
||||||
|
|
||||||
public HttpClientBuilderTests()
|
public HttpClientBuilderTests()
|
||||||
{
|
{
|
||||||
_provider = new Mock<IDelegatingHandlerHandlerProvider>();
|
_factory = new Mock<IDelegatingHandlerHandlerFactory>();
|
||||||
_house = new Mock<IDelegatingHandlerHandlerHouse>();
|
_builder = new HttpClientBuilder(_factory.Object);
|
||||||
_builder = new HttpClientBuilder(_house.Object);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void should_build_http_client()
|
public void should_build_http_client()
|
||||||
{
|
{
|
||||||
this.Given(x => GivenTheProviderReturns())
|
this.Given(x => GivenTheFactoryReturns())
|
||||||
.And(x => GivenARequest())
|
.And(x => GivenARequest())
|
||||||
.And(x => GivenTheHouseReturns())
|
|
||||||
.When(x => WhenIBuild())
|
.When(x => WhenIBuild())
|
||||||
.Then(x => ThenTheHttpClientShouldNotBeNull())
|
.Then(x => ThenTheHttpClientShouldNotBeNull())
|
||||||
.BDDfy();
|
.BDDfy();
|
||||||
@ -51,9 +48,8 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
() => fakeTwo
|
() => fakeTwo
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Given(x => GivenTheProviderReturns(handlers))
|
this.Given(x => GivenTheFactoryReturns(handlers))
|
||||||
.And(x => GivenARequest())
|
.And(x => GivenARequest())
|
||||||
.And(x => GivenTheHouseReturns())
|
|
||||||
.And(x => WhenIBuild())
|
.And(x => WhenIBuild())
|
||||||
.When(x => WhenICallTheClient())
|
.When(x => WhenICallTheClient())
|
||||||
.Then(x => ThenTheFakeAreHandledInOrder(fakeOne, fakeTwo))
|
.Then(x => ThenTheFakeAreHandledInOrder(fakeOne, fakeTwo))
|
||||||
@ -69,13 +65,6 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
_request = reRoute;
|
_request = reRoute;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheHouseReturns()
|
|
||||||
{
|
|
||||||
_house
|
|
||||||
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
|
|
||||||
.Returns(new OkResponse<IDelegatingHandlerHandlerProvider>(_provider.Object));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ThenSomethingIsReturned()
|
private void ThenSomethingIsReturned()
|
||||||
{
|
{
|
||||||
_response.ShouldNotBeNull();
|
_response.ShouldNotBeNull();
|
||||||
@ -91,18 +80,20 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
fakeOne.TimeCalled.ShouldBeGreaterThan(fakeTwo.TimeCalled);
|
fakeOne.TimeCalled.ShouldBeGreaterThan(fakeTwo.TimeCalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheProviderReturns()
|
private void GivenTheFactoryReturns()
|
||||||
{
|
{
|
||||||
_provider
|
var handlers = new List<Func<DelegatingHandler>>(){ () => new FakeDelegatingHandler()};
|
||||||
.Setup(x => x.Get())
|
|
||||||
.Returns(new List<Func<DelegatingHandler>>(){ () => new FakeDelegatingHandler()});
|
_factory
|
||||||
|
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
|
||||||
|
.Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenTheProviderReturns(List<Func<DelegatingHandler>> handlers)
|
private void GivenTheFactoryReturns(List<Func<DelegatingHandler>> handlers)
|
||||||
{
|
{
|
||||||
_provider
|
_factory
|
||||||
.Setup(x => x.Get())
|
.Setup(x => x.Get(It.IsAny<DownstreamReRoute>()))
|
||||||
.Returns(handlers);
|
.Returns(new OkResponse<List<Func<DelegatingHandler>>>(handlers));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WhenIBuild()
|
private void WhenIBuild()
|
||||||
|
@ -18,8 +18,7 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
public class HttpClientHttpRequesterTest
|
public class HttpClientHttpRequesterTest
|
||||||
{
|
{
|
||||||
private readonly Mock<IHttpClientCache> _cacheHandlers;
|
private readonly Mock<IHttpClientCache> _cacheHandlers;
|
||||||
private Mock<IDelegatingHandlerHandlerHouse> _house;
|
private Mock<IDelegatingHandlerHandlerFactory> _house;
|
||||||
private Mock<IDelegatingHandlerHandlerProvider> _provider;
|
|
||||||
private Response<HttpResponseMessage> _response;
|
private Response<HttpResponseMessage> _response;
|
||||||
private readonly HttpClientHttpRequester _httpClientRequester;
|
private readonly HttpClientHttpRequester _httpClientRequester;
|
||||||
private DownstreamContext _request;
|
private DownstreamContext _request;
|
||||||
@ -28,10 +27,8 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
|
|
||||||
public HttpClientHttpRequesterTest()
|
public HttpClientHttpRequesterTest()
|
||||||
{
|
{
|
||||||
_provider = new Mock<IDelegatingHandlerHandlerProvider>();
|
_house = new Mock<IDelegatingHandlerHandlerFactory>();
|
||||||
_provider.Setup(x => x.Get()).Returns(new List<Func<DelegatingHandler>>());
|
_house.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(new OkResponse<List<Func<DelegatingHandler>>>(new List<Func<DelegatingHandler>>()));
|
||||||
_house = new Mock<IDelegatingHandlerHandlerHouse>();
|
|
||||||
_house.Setup(x => x.Get(It.IsAny<DownstreamReRoute>())).Returns(new OkResponse<IDelegatingHandlerHandlerProvider>(_provider.Object));
|
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_loggerFactory
|
_loggerFactory
|
||||||
|
@ -13,6 +13,7 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
using TestStack.BDDfy;
|
using TestStack.BDDfy;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using Shouldly;
|
using Shouldly;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
public class HttpRequesterMiddlewareTests
|
public class HttpRequesterMiddlewareTests
|
||||||
{
|
{
|
||||||
@ -30,9 +31,7 @@ namespace Ocelot.UnitTests.Requester
|
|||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<HttpRequesterMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<HttpRequesterMiddleware>()).Returns(_logger.Object);
|
||||||
_next = async context => {
|
_next = context => Task.CompletedTask;
|
||||||
//do nothing
|
|
||||||
};
|
|
||||||
_middleware = new HttpRequesterMiddleware(_next, _loggerFactory.Object, _requester.Object);
|
_middleware = new HttpRequesterMiddleware(_next, _loggerFactory.Object, _requester.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ namespace Ocelot.UnitTests.Responder
|
|||||||
{
|
{
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Ocelot.DownstreamRouteFinder.Finder;
|
using Ocelot.DownstreamRouteFinder.Finder;
|
||||||
using Ocelot.Errors;
|
using Ocelot.Errors;
|
||||||
@ -32,9 +33,7 @@ namespace Ocelot.UnitTests.Responder
|
|||||||
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
_loggerFactory = new Mock<IOcelotLoggerFactory>();
|
||||||
_logger = new Mock<IOcelotLogger>();
|
_logger = new Mock<IOcelotLogger>();
|
||||||
_loggerFactory.Setup(x => x.CreateLogger<ResponderMiddleware>()).Returns(_logger.Object);
|
_loggerFactory.Setup(x => x.CreateLogger<ResponderMiddleware>()).Returns(_logger.Object);
|
||||||
_next = async context => {
|
_next = context => Task.CompletedTask;
|
||||||
//do nothing
|
|
||||||
};
|
|
||||||
_middleware = new ResponderMiddleware(_next, _responder.Object, _loggerFactory.Object, _codeMapper.Object);
|
_middleware = new ResponderMiddleware(_next, _responder.Object, _loggerFactory.Object, _codeMapper.Object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user