1. 程式人生 > >ASP.NET Core 2.2 基礎知識(四) URL重寫中間件

ASP.NET Core 2.2 基礎知識(四) URL重寫中間件

oid onf resp pub res 需要 only cat ddr

原文:ASP.NET Core 2.2 基礎知識(四) URL重寫中間件

說到URL重寫就不得不提URL重定向.

URL重定向

URL重定向是客戶端操作,指示客戶端訪問另一個地址的資源.這需要往返服務器,並且當客戶端對資源發出請求時,返回客戶端的重定向URL會出現在瀏覽器的地址欄中.

技術分享圖片

將請求重定向到不同的URL時,可指示重定向是永久的還是臨時的.如果是永久的,則使用"301"狀態碼.收到"301"狀態碼時,客戶端可能會緩存.如果是臨時的,則使用"302"狀態碼,以使客戶端將來不應存儲和重用重定向URL.

示例:

新建一個WebAPI項目;新增一個 TestController 控制器;在 Startup 類的 Configure 方法中增加如下代碼:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            ...other codes
            var options = new RewriteOptions();
            //options.AddRedirect("^redirect/(.*)", "api/test");//默認狀態碼為 302
            options.AddRedirect("^redirect/(.*)", "api/test", 301);
            app.UseRewriter(options);

            app.Run(async context =>
                {
                    //註意重定向和重寫URL兩種情況下,瀏覽器地址欄和頁面顯示的 URL 的區別.
                    await context.Response.WriteAsync($"URL:{context.Request.Path + context.Request.QueryString}"
); }); app.UseMvc(); }

啟動該項目,在瀏覽器地址欄輸入 : https://localhost:44303/redirect/123 後,

技術分享圖片

可以看出,客戶端一共請求了兩次,瀏覽器地址欄變成了重定向的URL.

URL重寫

技術分享圖片

URL重寫是服務器端操作.重寫URL不需要往返服務器,重寫的URL也不會返回客戶端,也不會出現在瀏覽器地址欄.

示例:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            ...other codes

            
var options = new RewriteOptions(); options.AddRewrite("^rewrite/(.*)", "api/test", true);//重寫URL,false/true 表示如果當前規則適用,是否跳過其他重寫規則. app.UseRewriter(options); app.Run(async context => { //註意重定向和重寫URL兩種情況下,瀏覽器地址欄和頁面顯示的 URL 的區別. await context.Response.WriteAsync($"URL:{context.Request.Path + context.Request.QueryString}"); }); app.UseMvc(); } }

在瀏覽器地址欄輸入 : https://localhost:44303/rewrite/1

技術分享圖片


RewriteOptions 類型提供了一個 Add 方法,接收一個委托.當請求地址符合一個規則後,方法傳遞的委托便會執行.這裏以修改 reContext.Result 的值為例.示例:

            {
                RewriteOptions options = new RewriteOptions();
                options.AddRewrite("^rewrite*", "test", true).Add(reContext =>
                {
                    reContext.Result = RuleResult.EndResponse;
                });
                app.UseRewriter(options);
                app.Run(async context => { await context.Response.WriteAsync(context.Request.Path + context.Request.QueryString); });
            }

只有請求地址符合規則時才會執行 app.Run(async context => { await context.Response.WriteAsync(context.Request.Path + context.Request.QueryString); }) 這句代碼.

測試圖如下:

技術分享圖片

可以看到,上面的請求不符合規則,頁面上什麽都沒顯示;

下面的請求符合規則,頁面顯示出了重寫後的請求路徑.

上面所有重寫的示例中,重寫的規則都是寫在代碼裏面的,而ASP.NET Core 還提供了從文件中讀取規則的方式.

新建一個文件夾 Rule ,添加一個 IISUrlRewrite.xml 文件,內容如下:

<rewrite>
  <rules>
    <rule name="MyIISUrlRewrite" stopProcessing="true">
      <match url="^rewrite/(.*)"/>
      <!--還 沒發現 appendQueryString = false 和 true 的區別-->     
      <action type="Rewrite" url="api/values/{R:1}" appendQueryString="false"/>
    </rule>
  </rules>
</rewrite>

修改 Configure 方法:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            ......
            var options = new RewriteOptions();

            //方法一:
            //using (StreamReader sr = File.OpenText(Path.Combine(env.ContentRootPath, @"Rule\IISUrlRewrite.xml")))
            //{
            //    options.AddIISUrlRewrite(sr);
            //    app.UseRewriter(options);
            //}

            //方法二:
            var fileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Rule"));
            options.AddIISUrlRewrite(fileProvider, "IISUrlRewrite.xml");
            app.UseRewriter(options);


            app.Run(async context =>
                {
                    await context.Response.WriteAsync(context.Request.Path + context.Request.QueryString);
                });

            app.UseMvc();
        }

圖就不上了.

雖然還沒用 ASP.NET Core 開發過任何項目,但是我覺得下面這種重寫和重定向的方法或許會是用得最多的,因為它足夠靈活.

    public class MyRule : IRule
    {
        //可以自定義構造函數,做一些驗證
        //public MyRule(string extension, string newPath)
        //{
        //    if (string.IsNullOrEmpty(extension))
        //    {
        //        throw new ArgumentException(nameof(extension));
        //    }
        //    if (!Regex.IsMatch(extension, @"^rewrite*"))
        //    {
        //        throw new ArgumentException("Invalid extension", nameof(extension));
        //    }
        //    if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
        //    {
        //        throw new ArgumentException("Invalid path", nameof(newPath));
        //    }

        //    _extension = extension;
        //    _newPath = new PathString(newPath);
        //}

        //private readonly string _extension;
        //private readonly PathString _newPath;

        private readonly string _extension;
        private readonly string _newPath;
        public MyRule(string extension, string newPath)
        {
            _extension = extension;
            _newPath = newPath;
        }


        public void ApplyRule(RewriteContext context)
        {
            HttpRequest request = context.HttpContext.Request;
            HttpResponse response = context.HttpContext.Response;

            //可以重寫
            request.Path = new PathString(_newPath);
            context.Result = RuleResult.SkipRemainingRules;

            //可以重定向
            //if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
            //{
            //    response.StatusCode = StatusCodes.Status302Found;
            //    context.Result = RuleResult.EndResponse;
            //    response.Headers[HeaderNames.Location] = _newPath;
            //}
        }
    }

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

            RewriteOptions options = new RewriteOptions();
            options.Add(new MyRule("rewrite","/api/test"));
            app.UseRewriter(options);

            app.UseHttpsRedirection();
            app.UseMvc();
        }
    }

ASP.NET Core 2.2 基礎知識(四) URL重寫中間件