說到URL重寫就不得不提URL重定向.api
URL重定向瀏覽器
URL重定向是客戶端操做,指示客戶端訪問另外一個地址的資源.這須要往返服務器,而且當客戶端對資源發出請求時,返回客戶端的重定向URL會出如今瀏覽器的地址欄中.緩存
將請求重定向到不一樣的URL時,可指示重定向是永久的仍是臨時的.若是是永久的,則使用"301"狀態碼.收到"301"狀態碼時,客戶端可能會緩存.若是是臨時的,則使用"302"狀態碼,以使客戶端未來不該存儲和重用重定向URL.服務器
示例:app
新建一個WebAPI項目;新增一個 TestController 控制器;在 Startup 類的 Configure 方法中增長以下代碼:async
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 後,ide
能夠看出,客戶端一共請求了兩次,瀏覽器地址欄變成了重定向的URL.函數
URL重寫測試
URL重寫是服務器端操做.重寫URL不須要往返服務器,重寫的URL也不會返回客戶端,也不會出如今瀏覽器地址欄.ui
示例:
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 類型提供了不少重寫和重定向的方法,除了上述的 AddRedirect , AddRewrite 外,還有兩個比較好玩的方法.
1.Add(Action<RewriteContext> applyRule)
接收一個委託.當請求地址符合一個規則後,方法傳遞的委託便會執行.這裏以修改 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); }) 這句代碼.
測試圖以下:
能夠看到,上面的請求不符合規則,頁面上什麼都沒顯示;下面的請求符合規則,頁面顯示出了重寫後的請求路徑.
2.AddRedirectToHttps
該方法能夠將 HTTP 請求重定向到採用 HTTPS 的相同主機和路徑.
新建一個 WebAPI 項目,可是不勾選 "爲HTTPS配置" 選項.
修改 Configure 方法.
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } var options = new RewriteOptions(); options.AddRedirectToHttps(statusCode: 301, sslPort: 9527); app.UseRewriter(options); app.UseMvc(); }
在瀏覽器地址欄輸入該項目地址 : http://localhost:50588 ,會重定向到 https://localhost:9527 , 如圖.
上面全部重寫的示例中,重寫的規則都是寫在代碼裏面的,而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(); } }
完