Ocelot
Ocelot copied to clipboard
Use custom pipeline middleware implemented as a class instead of a Func delegate
Expected Behavior / New Feature
Be able to create a custom middleware implementation like:
public class CustomAuthorizationMiddleware : OcelotMiddleware
{
private readonly RequestDelegate _next;
public CustomAuthorisationMiddleware(
RequestDelegate next,
IOcelotLoggerFactory loggerFactory)
:base(loggerFactory.CreateLogger<CustomAuthorizationMiddleware>())
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
// logic goes here
}
}
Actual Behavior / Motivation for New Feature
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var configuration = new OcelotPipelineConfiguration
{
AuthorizationMiddleware = async (context, next) =>
{
// Logic goes here
await next.Invoke();
}
};
app.UseOcelot(configuration)
.Wait();
}
I really needed that myself and ended up building some tooling for it that you can find here : https://gist.github.com/cguyonnet/650ca02ac87e33ea24814f0cb3e7e852
Basically it will generate an OcelotPipelineConfiguration that will encapsulate your class-based middleware...
Sweet! Thanks a lot
@cguyonnet Thanks a lot! This really helped in my case. I needed to update the headers of the downstream calls with values I get from other services. The ability to get dependencies injected into the Ocelot middleware was crucial for this flow and your code works like a charm for this. Thanks again 😄
Hi, team when we can implement this one, so i can use nuget without change the source code?
@ghost commented on Nov 23, 2018
Well... It is interesting... Do you believe that delegates are restriction for you but middleware classes are not, right? But you can define local services variable with all services from DI container like that:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var configuration = new OcelotPipelineConfiguration
{
AuthorizationMiddleware = async (context, next) =>
{
var service1 = app.ApplicationServices.GetService<IService1>();
var service2 = app.ApplicationServices.GetService<IService2>();
var obj1 = service1.DoSomething1();
var obj2 = service2.DoSomething2();
// Logic goes here
await next.Invoke();
}
};
app.UseOcelot(configuration).Wait();
}
If it looks ugly for you then you could encapsulate logic into a class:
public class CustomAuthorizationMiddleware : OcelotMiddleware
{
private readonly OcelotRequestDelegate _next;
public CustomAuthorizationMiddleware(
OcelotRequestDelegate next,
IOcelotLoggerFactory loggerFactory)
: base(loggerFactory.CreateLogger<CustomAuthorizationMiddleware>())
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
// logic goes here
await _next.Invoke(context);
}
}
and
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
var factory = app.ApplicationServices.GetService<IOcelotLoggerFactory>();
var configuration = new OcelotPipelineConfiguration
{
AuthorizationMiddleware = async (context, next) =>
{
RequestDelegate del = context => next.Invoke();
var middleware = new CustomAuthorizationMiddleware(del, factory);
await middleware.Invoke(context);
}
};
app.UseOcelot(configuration).Wait();
}
This design approach above doesn't require huge refactoring of Ocelot core and pipeline, in comparison to the @cguyonnet solution on Mar 1, 2019.
@cguyonnet commented on Mar 1, 2019
Great design & solution! 🤩 But unfortunately it has no backward compatibility. Seems it has a lot of breaking changes. Your opinion?
@pilgren commented on Mar 19, 2020
You can process your headers by custom Delegating Handler 😉 So, no need to write custom middleware and attach to the pipeline with overriding standard Ocelot middleware.