导航

01-005 HttpAbstractions 之 MapMiddleware

Posted on 2015-03-05 15:43  DotNet1010  阅读(147)  评论(0)    收藏  举报

MapMiddleware 是当   Request.Path  匹配某一给定的内容时 需要执行给定操作的一个中间件。

调用的代码为:

  public static IApplicationBuilder Map([NotNull] this IApplicationBuilder app, [NotNull] string pathMatch, [NotNull] Action<IApplicationBuilder> configuration)
  {
     return Map(app, new PathString(pathMatch), configuration);
  }

 具体使用的例子如:

 //To gracefully shutdown the server - Not for production scenarios
app.Map("/shutdown", shutdown =>
{
shutdown.Run(async context =>
{
var appShutdown = context.ApplicationServices.GetService<IApplicationShutdown>();
appShutdown.RequestShutdown();
await Task.Delay(10 * 1000, appShutdown.ShutdownRequested);
    if (appShutdown.ShutdownRequested.IsCancellationRequested)
    {
       await context.Response.WriteAsync("Shutting down gracefully");
    }
   else
    {
    await context.Response.WriteAsync("Shutting down token not fired");
     }
});
---------Run 方法结束 此处调用了RunExtension 中的 Run([NotNull] this IApplicationBuilder app, [NotNull] RequestDelegate handler) });

 匹配的地址为:

www.testSite.com/shutdown

www.testSite.com/shutdown/testaction

不匹配如下地址: www.testSite.com/shutdown123

 MapMiddleware 对应的RequestDelegate 代码如下:

   public async Task Invoke([NotNull] HttpContext context)
        {
            PathString path = context.Request.Path;
            PathString remainingPath;
            if (path.StartsWithSegments(_options.PathMatch, out remainingPath))
            {
                // Update the path
                PathString pathBase = context.Request.PathBase;
                context.Request.PathBase = pathBase + _options.PathMatch;
                context.Request.Path = remainingPath;

                await _options.Branch(context);

                context.Request.PathBase = pathBase;
                context.Request.Path = path;
            }
            else
            {
                await _next(context);
            }
        }

 另外:SignalR 中的代码:

public static IApplicationBuilder UseSignalR(this IApplicationBuilder builder)
{
    return builder.UseSignalR("/signalr");
}

 public static IApplicationBuilder UseSignalR(this IApplicationBuilder builder, string path)
 {
   return builder.Map(path, subApp => subApp.RunSignalR());
}

此处也调用了 Map 方法。

 具体的Map实现代码:

 public static IApplicationBuilder Map([NotNull] this IApplicationBuilder app, PathString pathMatch, [NotNull] Action<IApplicationBuilder> configuration)
        {
            if (pathMatch.HasValue && pathMatch.Value.EndsWith("/", StringComparison.Ordinal))
            {
                throw new ArgumentException("The path must not end with a '/'", "pathMatch");
            }

            // create branch
            var branchBuilder = app.New();
            configuration(branchBuilder);
            var branch = branchBuilder.Build();

            var options = new MapOptions()
            {
                Branch = branch,
                PathMatch = pathMatch,
            };
            return app.Use(next => new MapMiddleware(next, options).Invoke);
        }

 上述代码中为什么要 create branch ? 为什么要修改PathBase? 这样可以实现嵌套Map:代码如下:

  builder.Map("/route1", map =>
   {
                map.Map((string)"/subroute1", UseSuccess);
                map.Run(NotImplemented);
   });