The principle of ASP.NET Core endpoint routing

Endpoint routing ( Endpoint Routing) first appeared in ASP.NET Core2.2the ASP.NET Core3.0promotion to a first-class citizen.
Insert picture description here

Endpoint RoutingMotivation

Before the emergence of endpoint routing, we generally define MVC middleware resolution routing at the end of the request processing pipeline. This approach means that in the processing pipeline, the middleware before the MVC middleware will not be able to obtain routing information.

Routing information is very useful for some middleware, such as CORS, authentication middleware (routing information may be used in the authentication process).

At the same time, endpoint routing extracts the endpoint concept, decouples routing matching logic, and request distribution.

Endpoint RoutingMiddleware

Consists of a pair of middleware:

  1. UseRoutingAdd route matching to the middleware pipeline. The middleware looks at the set of endpoints defined in the application and selects the best match based on the request.
  2. UseEndpointsAdd endpoint execution to the middleware pipeline. MapGet, And MapPostother methods connect the processing logic to the routing system; other methods connect the ASP.NET Core framework features to the routing system.
  3. MapRazorPages for Razor Pages
  4. MapControllers for controllers
  5. MapHub< THub> for SignalR
  6. MapGrpcService< TService> for gRPC

The middleware upstream of this pair of middleware: always cannot perceive Endpoint;
the middleware between this pair of middleware will perceive the matched Endpointand have the ability to add processing logic; it
UseEndpointsis an end-point middleware; if
there is no match, then UseEndpointsAfter entering the middleware.

Placed UseRouting, UseEndpointsbetween authentication and authorization middleware:
perception endpoint information is matched; the scheduling Endpointbefore the application authorization policy.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    
    
    if (env.IsDevelopment())
    {
    
    
        app.UseDeveloperExceptionPage();
    }

    // Matches request to an endpoint.
    app.UseRouting();

    // Endpoint aware middleware. 
    // Middleware can use metadata from the matched endpoint.
    app.UseAuthentication();
    app.UseAuthorization();

    // Execute the matched endpoint.
    app.UseEndpoints(endpoints =>
    {
    
    
        // Configure the Health Check endpoint and require an authorized user.
        endpoints.MapHealthChecks("/healthz").RequireAuthorization();

        // Configure another endpoint, no authorization requirements.
        endpoints.MapGet("/", async context =>
        {
    
    
            await context.Response.WriteAsync("Hello World!");
        });
    });
}

The /healthhealth check is defined above . The endpoint defines the IAuthorizeDatametadata and requires authentication before performing the health check.


We UseRouting, UseEndpointsadd a little test code between: Perception endpoints:

   app.Use(next => context =>
    {
    
    
        var endpoint = context.GetEndpoint();
        if (endpoint is null)
        {
    
    
            return Task.CompletedTask;
        }
        Console.WriteLine($"Endpoint: {endpoint.DisplayName}");

        if (endpoint is RouteEndpoint routeEndpoint)
        {
    
    
            Console.WriteLine("Endpoint has route pattern: " +
                routeEndpoint.RoutePattern.RawText);
        }

        foreach (var metadata in endpoint.Metadata)
        {
    
    
            Console.WriteLine($"Endpoint has metadata: {metadata}");
        }
        return next(context);
    });

When requesting /healthz, I perceive the AuthorizeAttributemetadata and
Insert picture description here
guess that if the authentication and authorization middleware is to /healthzwork properly, it will inevitably respond to this AuthorizeAttributemetadata.

So flipping through the Github AuthorizationMiddleware 3.0 source code: I found that the request processing delegation really paid attention Endpoint, and extracted the IAuthorizeDataauthorization information in the metadata .

// ---- 截取自https://github.com/dotnet/aspnetcore/blob/master/src/Security/Authorization/Policy/src/AuthorizationMiddleware.cs-----
if (endpoint != null)
{
    
    
    context.Items[AuthorizationMiddlewareInvokedWithEndpointKey] = AuthorizationMiddlewareWithEndpointInvokedValue;
}
var authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>() ?? Array.Empty<IAuthorizeData>();
var policy = await AuthorizationPolicy.CombineAsync(_policyProvider, authorizeData);
if (policy == null)
{
    
    
     await _next(context);
     return;
}
var policyEvaluator = context.RequestServices.GetRequiredService<IPolicyEvaluator>();
......

What the test code perceives is AuthorizeAttributeindeed the realization of the IAuthorizeDatainterface.

bingo, guess the source code verification.

in conclusion

Endpoint routing: Allows ASP.NET Core applications to determine the endpoints to be scheduled early in the middleware pipeline, so that subsequent middleware can use this information to provide functions that cannot be provided by the current pipeline configuration.

This makes the ASP.NET Core framework more flexible and strengthens the concept of endpoints. It decouples routing matching and parsing functions from endpoint scheduling functions.

Guess you like

Origin blog.csdn.net/WuLex/article/details/112109030