Search code examples
asp.net-coremicroservices

Asp.net core middleware to run logic based on request url


I have an .net core application that works as api gateway and authentication service at the same time. The authentication controller looks like this:

[AllowAnonymous]
    [HttpPost, Route("request")]
    public IActionResult RequestToken([FromBody] TokenRequest request)
    {

        string token = "";
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }


        if (_authService.IsAuthenticated(request, out token))
        {
            return Ok(token);
        }

        return BadRequest("Invalid Request");
    }

Is there a way to crate a middleware that can distinguish the request url so I can redirect it to the controller when it is smth like "/auth" and "OTHERS". The "OTHERS" should be redirected to a service, which works running the following in Configure method:

app.Run(async (context) =>
            {
                using (var serviceScope = app.ApplicationServices.CreateScope())
                {
                    var routing = serviceScope.ServiceProvider.GetService<IRoutingService>();

                    var content = await routing.RouteRequest(context.Request);
                    await context.Response.WriteAsync(await content.Content.ReadAsStringAsync());
                    content.Dispose();

                    // Seed the database.
                }
            });

Solution

  • You can create a middleware for "others" requests and then map to it using Map method:

    • So you have an interface and an implementation, e.g:
        public interface IRoutingService
        {
            Task<HttpResponseMessage> RouteRequest(HttpRequest request);
        }
    
        public sealed class RoutingService : IRoutingService
        {
            public Task<HttpResponseMessage> RouteRequest(HttpRequest request)
            {
                // your code    
            }
        }
    
    • Add it to services:
        public class Startup
        {
            public void ConfigureServices(IServiceCollection services)
            {
                services.AddTransient<IRoutingService, RoutingService>();
            }
        }
    
    • Define a middleware using dependency injection in constructor for IRoutingService type:
        public static class OthersExtensions
        {
            public static IApplicationBuilder UseOthers(this IApplicationBuilder builder)
            {
                return builder.UseMiddleware<OthersMiddleware>();
            }
        }
    
        public sealed class OthersMiddleware
        {
            private readonly IRoutingService routing;
    
            public OthersMiddleware(RequestDelegate _, IRoutingService routing) => this.routing = routing;
    
            public async Task Invoke(HttpContext context)
            {
                var content = await routing.RouteRequest(context.Request);
    
                await context.Response.WriteAsync(await content.Content.ReadAsStringAsync());
    
                content.Dispose();
            }
        }
    
    • Use it:
        public class Startup
        {
            public void Configure(IApplicationBuilder app)
            {
                app.Map("/others", builder => builder.UseOthers());
            }
        }
    
    • And for the authentication controller just specify the route using RouteAttribute:
        [Route("auth")]
        public class AuthenticationController
        {
        }