首先建立扩展函数相关类
/// <summary>
/// 注册ocelot中间件
/// </summary>
public static class DemoOcelotExtension
{
public static IOcelotPipelineBuilder UseDemoResponseMiddleware(this IOcelotPipelineBuilder builder)
{
return builder.UseMiddleware<DemoResponseMiddleware>();
}
}
public static class OcelotPipelineExtensions
{
public static OcelotRequestDelegate BuildCustomeOcelotPipeline(this IOcelotPipelineBuilder builder,
OcelotPipelineConfiguration pipelineConfiguration)
{
// This is registered to catch any global exceptions that are not handled
// It also sets the Request Id if anything is set globally
builder.UseExceptionHandlerMiddleware();
// If the request is for websockets upgrade we fork into a different pipeline
builder.MapWhen(context => context.HttpContext.WebSockets.IsWebSocketRequest,
app =>
{
app.UseDownstreamRouteFinderMiddleware();
app.UseDownstreamRequestInitialiser();
app.UseLoadBalancingMiddleware();
app.UseDownstreamUrlCreatorMiddleware();
app.UseWebSocketsProxyMiddleware();
});
// Allow the user to respond with absolutely anything they want.
builder.UseIfNotNull(pipelineConfiguration.PreErrorResponderMiddleware);
// This is registered first so it can catch any errors and issue an appropriate response
builder.UseResponderMiddleware();
// Then we get the downstream route information
builder.UseDownstreamRouteFinderMiddleware();
// This security module, IP whitelist blacklist, extended security mechanism
builder.UseSecurityMiddleware();
//Expand other branch pipes
if (pipelineConfiguration.MapWhenOcelotPipeline != null)
{
foreach (var pipeline in pipelineConfiguration.MapWhenOcelotPipeline)
{
builder.MapWhen(pipeline);
}
}
// Now we have the ds route we can transform headers and stuff?
builder.UseHttpHeadersTransformationMiddleware();
// Initialises downstream request
builder.UseDownstreamRequestInitialiser();
// We check whether the request is ratelimit, and if there is no continue processing
builder.UseRateLimiting();
// This adds or updates the request id (initally we try and set this based on global config in the error handling middleware)
// If anything was set at global level and we have a different setting at re route level the global stuff will be overwritten
// This means you can get a scenario where you have a different request id from the first piece of middleware to the request id middleware.
builder.UseRequestIdMiddleware();
// Allow pre authentication logic. The idea being people might want to run something custom before what is built in.
builder.UseIfNotNull(pipelineConfiguration.PreAuthenticationMiddleware);
// Now we know where the client is going to go we can authenticate them.
// We allow the ocelot middleware to be overriden by whatever the
// user wants
if (pipelineConfiguration.AuthenticationMiddleware == null)
{
builder.UseAuthenticationMiddleware();
}
else
{
builder.Use(pipelineConfiguration.AuthenticationMiddleware);
}
// The next thing we do is look at any claims transforms in case this is important for authorisation
builder.UseClaimsToClaimsMiddleware();
// Allow pre authorisation logic. The idea being people might want to run something custom before what is built in.
builder.UseIfNotNull(pipelineConfiguration.PreAuthorisationMiddleware);
// Now we have authenticated and done any claims transformation we
// can authorise the request
// We allow the ocelot middleware to be overriden by whatever the
// user wants
if (pipelineConfiguration.AuthorisationMiddleware == null)
{
builder.UseAuthorisationMiddleware();
}
else
{
builder.Use(pipelineConfiguration.AuthorisationMiddleware);
}
// Now we can run the claims to headers transformation middleware
builder.UseClaimsToHeadersMiddleware();
// Allow the user to implement their own query string manipulation logic
builder.UseIfNotNull(pipelineConfiguration.PreQueryStringBuilderMiddleware);
// Now we can run any claims to query string transformation middleware
builder.UseClaimsToQueryStringMiddleware();
// Get the load balancer for this request
builder.UseLoadBalancingMiddleware();
// This takes the downstream route we retrieved earlier and replaces any placeholders with the variables that should be used
builder.UseDownstreamUrlCreatorMiddleware();
// Not sure if this is the best place for this but we use the downstream url
// as the basis for our cache key.
builder.UseOutputCacheMiddleware();
//We fire off the request and set the response on the scoped data repo
builder.UseHttpRequesterMiddleware();
//添加自定义测试中间件
builder.UseDemoResponseMiddleware();
return builder.Build();
}
private static void UseIfNotNull(this IOcelotPipelineBuilder builder,
Func<DownstreamContext, Func<Task>, Task> middleware)
{
if (middleware != null)
{
builder.Use(middleware);
}
}
}
/// <summary>
/// 自定义ocelot中间件
/// </summary>
public class DemoResponseMiddleware : OcelotMiddleware
{
private readonly OcelotRequestDelegate _next;
public DemoResponseMiddleware(OcelotRequestDelegate next, IOcelotLoggerFactory loggerFactory)
: base(loggerFactory.CreateLogger<DemoResponseMiddleware>())
{
_next = next;
}
public async Task Invoke(DownstreamContext context)
{
if (!context.IsError && context.HttpContext.Request.Method.ToUpper() != "OPTIONS")
{
Console.WriteLine("自定义中间件");
Console.WriteLine("自定义业务逻辑处理");
// 1、处理统一结果
// resutList resultMap
// 2、统一日志记录
// 3、做链路监控
// 4、性能监控
// 5、流量统计
}
else
{
await _next.Invoke(context);
}
}
}
在asp.net core中使用
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
// 1、添加网关Ocelot到ioc容器
services.AddOcelot().AddConsul().AddPolly();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// 2、使用网关
app.UseOcelot((build,config) => {
build.BuildCustomeOcelotPipeline(config); // 2.1 自定义ocelot中间件完成
}).Wait();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
}