mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-22 06:22:50 +08:00
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:
parent
8f4ae03290
commit
5c940acf0e
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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 =>
|
||||||
{
|
{
|
||||||
|
@ -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>>>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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 =>
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user