Owin中間件動手做

準備工作

首先通過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的管道概念其實簡單易懂,在程序啓動之前,向裏面插入中間件,中間件決定請求是否繼續向下走。在管道中的中間件可以拿到請求的所有信息以對請求進行處理,管道里的中間件執行結束之後,這個請求就被處理完成了,然後發回瀏覽器。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章