Expand other branch pipes (#416)

* Expand other branch pipes

* Expand other branch pipes

* Expand other branch pipes

* optimization Expand other branch pipes ,Add Unit test

*  I hope to add two attributes to IOcelotBuilder for easy extension.
This commit is contained in:
aqa510415008 2018-07-20 00:45:46 +08:00 committed by Tom Pallister
parent 8f4ae03290
commit 5c940acf0e
10 changed files with 107 additions and 21 deletions

View File

@ -4,11 +4,15 @@ using System;
using System.Net.Http; using System.Net.Http;
using IdentityServer4.AccessTokenValidation; using IdentityServer4.AccessTokenValidation;
using Ocelot.Middleware.Multiplexer; using Ocelot.Middleware.Multiplexer;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
namespace Ocelot.DependencyInjection namespace Ocelot.DependencyInjection
{ {
public interface IOcelotBuilder public interface IOcelotBuilder
{ {
IServiceCollection Services { get; }
IConfiguration Configuration { get; }
IOcelotBuilder AddStoreOcelotConfigurationInConsul(); IOcelotBuilder AddStoreOcelotConfigurationInConsul();
IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings); IOcelotBuilder AddCacheManager(Action<ConfigurationBuilderCachePart> settings);

View File

@ -55,6 +55,10 @@ namespace Ocelot.DependencyInjection
private readonly IServiceCollection _services; private readonly IServiceCollection _services;
private readonly IConfiguration _configurationRoot; private readonly IConfiguration _configurationRoot;
public IServiceCollection Services => _services;
public IConfiguration Configuration => _configurationRoot;
public OcelotBuilder(IServiceCollection services, IConfiguration configurationRoot) public OcelotBuilder(IServiceCollection services, IConfiguration configurationRoot)
{ {
_configurationRoot = configurationRoot; _configurationRoot = configurationRoot;

View File

@ -29,13 +29,19 @@
return builder; return builder;
} }
public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder builder, Action<OcelotPipelineConfiguration> pipelineConfiguration)
{
var config = new OcelotPipelineConfiguration();
pipelineConfiguration?.Invoke(config);
return await builder.UseOcelot(config);
}
public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration) public static async Task<IApplicationBuilder> UseOcelot(this IApplicationBuilder builder, OcelotPipelineConfiguration pipelineConfiguration)
{ {
var configuration = await CreateConfiguration(builder); var configuration = await CreateConfiguration(builder);
CreateAdministrationArea(builder, configuration); CreateAdministrationArea(builder, configuration);
if(UsingRafty(builder)) if (UsingRafty(builder))
{ {
SetUpRafty(builder); SetUpRafty(builder);
} }
@ -78,7 +84,7 @@
private static bool UsingRafty(IApplicationBuilder builder) private static bool UsingRafty(IApplicationBuilder builder)
{ {
var possible = builder.ApplicationServices.GetService(typeof(INode)) as INode; var possible = builder.ApplicationServices.GetService(typeof(INode)) as INode;
if(possible != null) if (possible != null)
{ {
return true; return true;
} }
@ -196,7 +202,7 @@
{ {
var ocelotConfiguration = provider.Get(); var ocelotConfiguration = provider.Get();
if(ocelotConfiguration?.Data == null || ocelotConfiguration.IsError) if (ocelotConfiguration?.Data == null || ocelotConfiguration.IsError)
{ {
ThrowToStopOcelotStarting(ocelotConfiguration); ThrowToStopOcelotStarting(ocelotConfiguration);
} }
@ -216,7 +222,7 @@
private static void CreateAdministrationArea(IApplicationBuilder builder, IInternalConfiguration configuration) private static void CreateAdministrationArea(IApplicationBuilder builder, IInternalConfiguration configuration)
{ {
if(!string.IsNullOrEmpty(configuration.AdministrationPath)) if (!string.IsNullOrEmpty(configuration.AdministrationPath))
{ {
builder.Map(configuration.AdministrationPath, app => builder.Map(configuration.AdministrationPath, app =>
{ {

View File

@ -1,6 +1,8 @@
namespace Ocelot.Middleware namespace Ocelot.Middleware
{ {
using Ocelot.Middleware.Pipeline;
using System; using System;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
public class OcelotPipelineConfiguration public class OcelotPipelineConfiguration
@ -38,5 +40,9 @@
/// This allows the user to implement there own query string manipulation logic /// This allows the user to implement there own query string manipulation logic
/// </summary> /// </summary>
public Func<DownstreamContext, Func<Task>, Task> PreQueryStringBuilderMiddleware { get; set; } public Func<DownstreamContext, Func<Task>, Task> PreQueryStringBuilderMiddleware { get; set; }
/// <summary>
/// This is an extension that will branch to different pipes
/// </summary>
public List<Func<IOcelotPipelineBuilder, Func<DownstreamContext, bool>>> MapWhenOcelotPipeline { get; } = new List<Func<IOcelotPipelineBuilder, Func<DownstreamContext, bool>>>();
} }
} }

View File

@ -80,13 +80,14 @@ namespace Ocelot.Middleware.Pipeline
var diagnosticListener = (DiagnosticListener)app.ApplicationServices.GetService(typeof(DiagnosticListener)); var diagnosticListener = (DiagnosticListener)app.ApplicationServices.GetService(typeof(DiagnosticListener));
var middlewareName = ocelotDelegate.Target.GetType().Name; var middlewareName = ocelotDelegate.Target.GetType().Name;
OcelotRequestDelegate wrapped = context => { OcelotRequestDelegate wrapped = context =>
{
try try
{ {
Write(diagnosticListener, "Ocelot.MiddlewareStarted", middlewareName, context); Write(diagnosticListener, "Ocelot.MiddlewareStarted", middlewareName, context);
return ocelotDelegate(context); return ocelotDelegate(context);
} }
catch(Exception ex) catch (Exception ex)
{ {
WriteException(diagnosticListener, ex, "Ocelot.MiddlewareException", middlewareName, context); WriteException(diagnosticListener, ex, "Ocelot.MiddlewareException", middlewareName, context);
throw ex; throw ex;
@ -117,7 +118,7 @@ namespace Ocelot.Middleware.Pipeline
private static void Write(DiagnosticListener diagnosticListener, string message, string middlewareName, DownstreamContext context) private static void Write(DiagnosticListener diagnosticListener, string message, string middlewareName, DownstreamContext context)
{ {
if(diagnosticListener != null) if (diagnosticListener != null)
{ {
diagnosticListener.Write(message, new { name = middlewareName, context = context }); diagnosticListener.Write(message, new { name = middlewareName, context = context });
} }
@ -125,7 +126,7 @@ namespace Ocelot.Middleware.Pipeline
private static void WriteException(DiagnosticListener diagnosticListener, Exception exception, string message, string middlewareName, DownstreamContext context) private static void WriteException(DiagnosticListener diagnosticListener, Exception exception, string message, string middlewareName, DownstreamContext context)
{ {
if(diagnosticListener != null) if (diagnosticListener != null)
{ {
diagnosticListener.Write(message, new { name = middlewareName, context = context, exception = exception }); diagnosticListener.Write(message, new { name = middlewareName, context = context, exception = exception });
} }
@ -160,6 +161,28 @@ namespace Ocelot.Middleware.Pipeline
return app.Use(next => new MapWhenMiddleware(next, options).Invoke); return app.Use(next => new MapWhenMiddleware(next, options).Invoke);
} }
public static IOcelotPipelineBuilder MapWhen(this IOcelotPipelineBuilder app, Func<IOcelotPipelineBuilder, Predicate> pipelineBuilderFunc)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
if (pipelineBuilderFunc == null)
{
throw new ArgumentNullException(nameof(pipelineBuilderFunc));
}
var branchBuilder = app.New();
var predicate = pipelineBuilderFunc.Invoke(app);
var branch = branchBuilder.Build();
var options = new MapWhenOptions
{
Predicate = predicate,
Branch = branch
};
return app.Use(next => new MapWhenMiddleware(next, options).Invoke);
}
private static Func<T, DownstreamContext, IServiceProvider, Task> Compile<T>(MethodInfo methodinfo, ParameterInfo[] parameters) private static Func<T, DownstreamContext, IServiceProvider, Task> Compile<T>(MethodInfo methodinfo, ParameterInfo[] parameters)
{ {
var middleware = typeof(T); var middleware = typeof(T);

View File

@ -28,6 +28,15 @@ namespace Ocelot.Middleware.Pipeline
// It also sets the Request Id if anything is set globally // It also sets the Request Id if anything is set globally
builder.UseExceptionHandlerMiddleware(); builder.UseExceptionHandlerMiddleware();
//Expand other branch pipes
if (pipelineConfiguration.MapWhenOcelotPipeline != null)
{
foreach (var pipeline in pipelineConfiguration.MapWhenOcelotPipeline)
{
builder.MapWhen(pipeline);
}
}
// If the request is for websockets upgrade we fork into a different pipeline // If the request is for websockets upgrade we fork into a different pipeline
builder.MapWhen(context => context.HttpContext.WebSockets.IsWebSocketRequest, builder.MapWhen(context => context.HttpContext.WebSockets.IsWebSocketRequest,
app => app =>

View File

@ -3,8 +3,13 @@ namespace Ocelot.UnitTests.Middleware
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Ocelot.DependencyInjection; using Ocelot.DependencyInjection;
using Ocelot.DownstreamRouteFinder.Middleware;
using Ocelot.DownstreamUrlCreator.Middleware;
using Ocelot.LoadBalancer.Middleware;
using Ocelot.Middleware; using Ocelot.Middleware;
using Ocelot.Middleware.Pipeline; using Ocelot.Middleware.Pipeline;
using Ocelot.Request.Middleware;
using Ocelot.WebSockets.Middleware;
using Pivotal.Discovery.Client; using Pivotal.Discovery.Client;
using Shouldly; using Shouldly;
using Steeltoe.Common.Discovery; using Steeltoe.Common.Discovery;
@ -26,6 +31,16 @@ namespace Ocelot.UnitTests.Middleware
.BDDfy(); .BDDfy();
} }
[Fact]
public void should_expand_pipeline()
{
this.Given(_ => GivenTheDepedenciesAreSetUp())
.When(_ => WhenIExpandBuild())
.Then(_ => ThenThePipelineIsBuilt())
.BDDfy();
}
private void ThenThePipelineIsBuilt() private void ThenThePipelineIsBuilt()
{ {
_handlers.ShouldNotBeNull(); _handlers.ShouldNotBeNull();
@ -36,6 +51,23 @@ namespace Ocelot.UnitTests.Middleware
_handlers = _builder.BuildOcelotPipeline(new OcelotPipelineConfiguration()); _handlers = _builder.BuildOcelotPipeline(new OcelotPipelineConfiguration());
} }
private void WhenIExpandBuild()
{
OcelotPipelineConfiguration configuration = new OcelotPipelineConfiguration();
configuration.MapWhenOcelotPipeline.Add((app) =>
{
app.UseDownstreamRouteFinderMiddleware();
app.UseDownstreamRequestInitialiser();
app.UseLoadBalancingMiddleware();
app.UseDownstreamUrlCreatorMiddleware();
app.UseWebSocketsProxyMiddleware();
return context => context.HttpContext.WebSockets.IsWebSocketRequest;
});
_handlers = _builder.BuildOcelotPipeline(new OcelotPipelineConfiguration());
}
private void GivenTheDepedenciesAreSetUp() private void GivenTheDepedenciesAreSetUp()
{ {
IConfigurationBuilder test = new ConfigurationBuilder(); IConfigurationBuilder test = new ConfigurationBuilder();

View File

@ -79,6 +79,8 @@ namespace Ocelot.UnitTests.Middleware
del.Invoke(_downstreamContext); del.Invoke(_downstreamContext);
} }
private void ThenTheFuncIsInThePipeline() private void ThenTheFuncIsInThePipeline()
{ {
_counter.ShouldBe(1); _counter.ShouldBe(1);