Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.neuro-tech.io/llms.txt

Use this file to discover all available pages before exploring further.

Middleware and Pipeline

Add CORS, logging, blocking logic, and route-aware behavior to the request pipeline

Why middleware matters

Middleware lets you run logic before or after an endpoint without putting that logic inside every controller action. Typical uses:
  • CORS
  • Request logging
  • Route-aware auditing
  • Short-circuiting blocked requests
  • Adding data to Context.Items

Prefix middleware

Use RegisterMiddleware(...) to attach middleware to a route path or path prefix.
Router.RegisterMiddleware("/projects/*", async (HttpContext Context, Action<HttpContext> Next) =>
{
    RouteFeature? Route = Context.GetFeature<RouteFeature>();

    Context.Items["matchedRoute"] = Route?.Route.ToString() ?? string.Empty;

    if (Context.Request.QueryParameters.Optional("blocked") == "true")
    {
        await Context.Response.Return(new RestApiErrorResponse("Blocked by middleware.", "blocked"));
        return;
    }

    Next(Context);
});
If the middleware writes the response and returns early, the endpoint is never called. Do not call Next(Context) after short-circuiting.

A practical CORS pattern

EndpointRouter Router = new EndpointRouter("/api", true);
CorsMiddleware Middleware = new CorsMiddleware(
[
    "https://app.example.com",
    "https://admin.example.com"
],
true);

Router.RegisterMiddleware("/users", async (HttpContext Context, Action<HttpContext> Next) =>
{
    await Middleware.Process(Context.Request, Context.Response);
    Next(Context);
});

Router.RegisterControllers(typeof(UsersController).Assembly);

Pipeline stages

Use the overload with MiddlewareStage when a middleware depends on data only available later:
  1. Infrastructure
  2. Routing
  3. PreAuthorization
  4. Authorization
  5. PostAuthorization
  6. PreHandler
  7. Handler
  8. PostHandler
  • Route parameters are available from Routing and later
  • Authorization state is available from Authorization and later
  • Handler is reserved for the endpoint itself

Attribute-based middleware

Attach middleware directly to controllers and methods with [Middleware].
[Controller]
[Route("/projects")]
[Middleware(typeof(ProjectAuditMiddleware), MiddlewareStage.Infrastructure)]
public sealed class ProjectsController : ControllerBase
{
    [HttpGet("/[projectId]")]
    [Middleware(typeof(ProjectRouteLoggingMiddleware), MiddlewareStage.Routing)]
    public Task<ProjectResponse> Get(string ProjectId)
    {
        return Task.FromResult(new ProjectResponse { ProjectId = ProjectId });
    }
}

public sealed class ProjectAuditMiddleware : MiddlewareBase
{
    public override Task Invoke(HttpContext Context, Action<HttpContext> Next)
    {
        Next(Context);
        return Task.CompletedTask;
    }
}

Default middleware behavior

  • RegisterMiddleware("/path", Middleware) defaults to PreAuthorization for all verbs
  • RegisterMiddleware(HttpMethodType.Get, "/path", Middleware) defaults to PostAuthorization
  • Controller-level [Middleware] defaults to PreAuthorization
  • Method-level [Middleware] defaults to PostAuthorization
  • Controller-level middleware runs before method-level middleware
  • Types declared in [Middleware] must inherit MiddlewareBase
Authorization builds directly on the middleware model and shows how protected endpoints are declared.