说到 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 也不会返回客户端, 也不会出现在浏览器地址栏.
示例:
- 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();
- }
- }
来源: https://www.cnblogs.com/refuge/p/10213596.html