zoukankan      html  css  js  c++  java
  • Owin中间件动手做

    摘要:本文目的是了解Owin基本原理。讲述如何从控制台创建一个自宿主的OwinHost,然后再编写一两个中间件

    准备工作

    首先通过VisualStudio创建一个控制台应用

    然后添加Owin的Nuget包引用

    需要的包如下

    Owin
    Microsoft.Owin
    Microsoft.Owin.Hosting
    Microsoft.Owin.Host.HttpListener
    

    准备工作到此结束

    编写OwinStartup类

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.Run(HandleRequest);
        }
        static Task HandleRequest(IOwinContext context)
        {
            context.Response.ContentType = "text/plain";
            return context.Response.WriteAsync("Hello world from myOwin");
        }
    }
    

    当OwinHost运行时,会首先加载Startup类,Configuration方法是必须有的,在Configuration方法中向Owin管道插入中间件,所有的请求都是中间件处理。

    在这个Configurationapp.Run(HandleRequest);方法的作用是向管道中添加一个没有后续中间件的中间件,一般来讲一个Owin管道中有许多中间件,不同的中间件处理不同的事情,在处理结束后选择性的调用后面的中间件,例如某个身份验证中间件可以在验证失败时结束请求。而app.Run方法就是插如一个没有后续事项的中间件。稍后我们会编写常规的中间件。

    这个中间件做的事很简单,就是向响应写入一个字符串,无论请求是什么结果都是一样的。

    在Main方法中启动Host

    static void Main(string[] args)
    {
        var url = "http://localhost:8080/";
        var opt = new StartOptions(url);
    
        using (WebApp.Start<Startup>(opt))
        {
            Console.WriteLine("Server run at " + url + " , press Enter to exit.");
            Console.ReadLine();
        }
    }
    

    StartOptions类用来指定一些启动参数,最少应该指定一个url,这里一并指定了使用8080端口

    启动程序控制台输出如下

    Server run at http://localhost:8080/ , press Enter to exit.
    

    用浏览器打开 http://localhost:8080/
    效果如下:

    `Hello world from myOwin`
    

    尝试更改路径你得到的始终是一个结果
    你可以尝试将Configuration中的代码注释掉,在运行程序,这是访问将得到空页面,Http代码也将是404,因为Owin管道中没有中间件处理请求。

    编写中间件

    我们编写一个名为Ding的中间件

    public class DingMiddleware : OwinMiddleware
    {
        public DingMiddleware(OwinMiddleware next) : base(next)
        {
        }
    
        public override Task Invoke(IOwinContext context)
        {
            if (context.Request.Path.Value.Equals("/home/index"))
            {
                context.Response.Write("hello world from home/index");
            }
            if (Next != null)
            {
                return Next.Invoke(context);
            }
            return Task.CompletedTask;
        }
    }
    

    这个中间件在检测到访问路径是/home/index时向Response中写入一句话,然后检测是否有下一个中间件,如果有就调用。

    添加中间件到Configuration

    可以直接在Configuration中加入app.Use<DingMiddleware>()来插入中间件,但是我们一般使用扩展方法来做这件事。

    public static class MyMidlewareExtention
    {
        public static IAppBuilder UseDing(this IAppBuilder app)
        {
            return app.Use<DingMiddleware>();
        }
    }
    

    修改Configuration中的代码:

    public void Configuration(IAppBuilder app)
    {
        app.UseDing();
        app.Run(HandleRequest);
    }
    

    现在管道中有两个中间件了,现在运行程序,在地址栏中输入http://localhost:8080/home/index将得到如下结果
    hello world from home/indexHello world from myOwin
    因为Ding中间件在处理之后继续调用了接下来的中间件
    输入其他路径将得到Hello world from myOwin这个结果

    如果将Configuration中的两个中间件位置调换,的到的结果只有一个Hello world from myOwin,因为app.Run(HandleRequest);不执行后续的中间件。

    第二个中间件

    public class DiDiDiMiddleware : OwinMiddleware
    {
        public DiDiDiMiddleware(OwinMiddleware next) : base(next)
        {
        }
    
        public override Task Invoke(IOwinContext context)
        {
            if (context.Request.QueryString.Value == "boom")
            {
    			context.Response.Write("Boom! Boom! Boom!");
                return Task.CompletedTask;
            }
            if (Next != null)
            {
                return Next.Invoke(context);
            }
            return Task.CompletedTask;
        }
    }
    

    这个中间件在地址栏QueryString(?后边的部分)等于boom时结束请求。

    MyMidlewareExtention代码修改如下:

    public static class MyMidlewareExtention
    {
        public static IAppBuilder UseDing(this IAppBuilder app)
        {
            return app.Use<DingMiddleware>();
        }
        public static IAppBuilder UseDiDiDi(this IAppBuilder app)
        {
            return app.Use<DiDiDiMiddleware>();
        }
    }
    

    Startup类修改如下:

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
    
            app.UseDiDiDi();
            app.UseDing();
        }
    }
    

    这里去掉了app.Run此时,对于非/home/index的请求会得到404,所以我们暂时改动下代码将HandleRequest方法封装成一个默认的中间件

    代码改动如下:

    public class DefaultMiddleware : OwinMiddleware
    {
        public DefaultMiddleware(OwinMiddleware next) : base(next)
        {
        }
    
        public override Task Invoke(IOwinContext context)
        {
            var path = context.Request.Path.Value;
            context.Response.Write($"hey you come from {path}!");
            return Task.CompletedTask;
        }
    }
    

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseDiDiDi();
            app.UseDing();
            app.UseDefault();
        }
    }
    

    运行程序观察结果是否符合预期。
    当地址中含有?boom时会的到一个Boom!Boom!Boom!

    总结:Owin的管道概念其实简单易懂,在程序启动之前,向里面插入中间件,中间件决定请求是否继续向下走。在管道中的中间件可以拿到请求的所有信息以对请求进行处理,管道里的中间件执行结束之后,这个请求就被处理完成了,然后发回浏览器。

  • 相关阅读:
    程序从命令行接收多个数字,求和之后输出结果。
    动态规划(1)
    软件工程个人作业(4)
    冲刺2 01
    构建之法
    水王
    大道至简第七章读后感
    构建之法03
    团队冲刺第四天
    团队冲刺第三天
  • 原文地址:https://www.cnblogs.com/rocketRobin/p/7844423.html
Copyright © 2011-2022 走看看