【ASP.NET Core】URL重写
今天老周和大伙伴们聊聊有关 Url Rewrite 的事情,翻译过来就是 URL 重写。
这里不得不提一下,URL重定向与重写的不同。
1、URL重定向是客户端(通常是浏览器)向服务器请求地址A,然后服务器要求重定向到B,返回状态码 301 或 302 给客户端,并且夹带一个 Location 的标头,其值表示要重定向的目标 URL,即B;随后客户端再用B向服务器发起请求,若成功,服务器返回内容并夹带状态码 200。
2、URL重写只在服务器上转换URL,当客户端请求地址A进入服务器后,服务器自行处理并转向B。最后返回B地址的内容,夹带状态码 200。此过程只在服务器上发生,不需要与客户端进行多次通信。因此浏览器地址栏中的URL也不会发生变化。
-------------------------------------------------- 超级分界线 ------------------------------------------------------
实现 URL 重写不需要向服务容器注册功能类,但可以在 Service 集合中配置 Options。你需要通过 RewriteOptions 对象来指定重定向的规则。定义规则的方法是实现 IRule 接口。此接口只有一个 ApplyRule 方法。在实现该方法时,根据需要修改 HttpContext.Request.Path 来设置新的 URL。
------------------------------------------------------------------------------------------------------------------------
下面咱们直接上示例,这里我写了一个简单的URL重写规则。
public sealed class MyRule : IRule
{
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
var oldPath = request.Path;
// 正则表达式来匹配
var match = Regex.Match(oldPath, "/ft(\\d+)");
if(match == null || match.Success == false)
{
context.Result = RuleResult.ContinueRules;
return;
}
// 找出匹配的分组
var matchedval = match!.Groups[1].Value;
// 新的URL
PathString newPath = "/fight-action/" + matchedval;
request.Path = newPath; //修改为新URL
context.Result = RuleResult.SkipRemainingRules;
}
}
这个规则是这样的:客户端请求 https://localhost/ft3,通过正则表达式,找出URL中的数值 3 ,然后改为新的 URL:https://localhost/fight-action/3。即
https://host/ft{数值} ----> https://host/fight-action/{数值}
为什么要重写 URL 呢,假设网站内部实现某功能的 URL 很长,很难看,很难记忆,用户看到它就想抽它。为了让用户觉得好记好看,在公开的前台 UI 或者 Web API 中使用一个更短更方便记忆的 URL。这又是为何呢?老周做个假设:假设你有个新闻系统,按照最初的开发设计,写一篇新闻的 URL 是 http://killer/news_manager/addnew。嗯,这个路径逻辑清晰、层次分明、表义明了(对开发人员来说,这样好维护,模块化);可对用户来说,他哪管你模块化还是分尸化,他就觉得这太长,不好记,也不好输入。行,咱们给来个 URL 重写,对外公开的 URL 变成 http://killer/addnews,而服务器内部还是转回原来的地址来处理,但客户端是毫无察觉的。
还有一种情况是网站修改了,后台的结构变了,API 的结构变了,可你懒得把所有前台 UI 改动。于是,你也可以写个 URL 重写规则,让旧 URL 自动转到新的 URL 上,同样客户端毫无察觉的(明修____,暗渡____)。
回到 ASP.NET Core 主体代码,这里为了节省体力和脑力,老周就不做 HTML 页了,直接 MapGet 代表每个页面。
// 模拟一些路径
app.MapGet("/", () => "燕双鹰战斗仪");
app.MapGet("/fight-action/{mode}", (int mode) => mode switch
{
0 => "全自动扫射装载中……",
1 => "装逼两分钟,开挂三小时",
2 => "无限子弹碾压",
3 => "我赌你的枪里没有子弹",
4 => "脑浆警告",
5 => "像你这样的人应该怎么改变,不会改变的,只有X",
_ => "外挂已到期"
});
路径 /fight-action 后面一段是路由参数 mode,然后这个数值会随同参数 mode 传入lambda 表达式,内部根据 mode 的值返回不同的字符串。
使用 URL 重写我们不需要向服务容器添加依赖注入对象,直接在 HTTP 管线上以中间件方式 Use 一下即可。
app.UseRewriter();
不过,这个无参数调用是未添加任何自定义重写规则的,咱们有两种方法添加规则。
第一种方法:保持 UseRewriter 方法无参数调用,使用服务容器来 Config 一下 RewriteOptions 选项类。这个方法实际是在服务容器中生成了 IOptions<RewriteOptions> 对象,中间件类 RewriteMiddleware 的构造函数会注入这个选项类实例。
// 以下为 .NET 源代码
public RewriteMiddleware(
RequestDelegate next,
IWebHostEnvironment hostingEnvironment,
ILoggerFactory loggerFactory,
IOptions<RewriteOptions> options)
{
// ……
_next = next;
_options = options.Value;
_fileProvider = _options.StaticFileProvider ?? hostingEnvironment.WebRootFileProvider;
_logger = loggerFactory.CreateLogger<RewriteMiddleware>();
}
现在,咱们把刚刚写的 MyRule 规则配置一下。
var builder = WebApplication.CreateBuilder(args);
// 配置 rewrite options
builder.Services.Configure<RewriteOptions>(rwo =>
{
rwo.Add(new MyRule());
});
var app = builder.Build();
第二种方法:在HTTP 管理线中调用 UseRewriter 方法前,直接 new 一个 RewriteOptions 实例,然后添加刚刚写的规则。最后调用 UseRewriter 方法的带参数版本,把 options 传给它即可。
RewriteOptions rwopt = new();
rwopt.Add(new MyRule());
app.UseRewriter(rwopt);
两种方法任选其一就可以了,不需要重复配置。
现在咱们运行一下示例。
默认打开主页是这样的。

然后把 URL 改为 /ft3。

URL 已经跳转,不过浏览器地址栏不会有变化,而且不会返回 301、302 给客户端,因为这个跳转过程是在服务器上完成的。
------------------------------------ 未知分界线 -------------------------------------------
其实,RewriteOptions 补充了一些扩展方法,使得咱们在简单重写URL(不需要特复杂的逻辑分析,用正则就能搞定的)时可以不去实现 IRule 接口。故,咱们这个示例可以改成这样更简洁的实现。
var builder = WebApplication.CreateBuilder(args);
// 配置 rewrite options
builder.Services.Configure<RewriteOptions>(rwo =>
{
rwo.AddRewrite("ft(\\d+)", "fight-action/$1", true);
});
var app = builder.Build();
第一个参数是正则表达式,括号中表示捕捉为一个分组,第二个参数是新的 URL,其中“$1”表示引用正则表达式中捕捉的分组编号,咱们这个正则表达式中只有一个分组,即捕捉数值的 \d+,所以用 $1 引用它;如果有其他分组,那就依此类推,$2、$3、$4。它的意思就是引用捕捉到这个分组的值。如,匹配 ft2,捕捉到数值 2,然后替换 $1,使新的URL为 fight-action/2。注意在匹配和替换的 URL 都不用“/”开头,反正类库在处理时也会删除“/”的,所以我们就没必须加“/”。
再测试一下。
运行后,转到 /ft5,结果如下。

好了,今天的节目就到此了,下次有空咱们再聊。
【ASP.NET Core】URL重写的更多相关文章
- ASP.net的url重写
http://blog.csdn.net/windok2004/article/details/2432691 1. 有关于URL的重写,本文也只是拿来主意.相继有MS的组件“URLRewriter” ...
- ASP.NET MVC URL重写与优化(1)-使用Global路由表定制URL
ASP.NET MVC URL重写与优化(1)-使用Global路由表定制URL 引言--- 在现今搜索引擎制霸天下的时代,我们不得不做一些东西来讨好爬虫,进而提示网站的排名来博得一个看得过去的流量. ...
- asp.net 页面url重写
不更改情况下,页面路径为index.aspx?id=1,现在输入页面路径index/1时,也能访问到页面,这一过程叫做url重写 ①:在一个类里制定路径重写规则,以下为自定义UrlRewriterFi ...
- (转)ASP.net的url重写
1. 有关于URL的重写,本文也只是拿来主意.相继有MS的组件“URLRewriter”和在Global.asax里的“Application_BeginRequest()”编码方式,以及IIS里的I ...
- ASP.NET MVC URL重写与优化(进阶篇)-继承RouteBase
原文地址:http://www.51csharp.com/MVC/882.html ASP.NET MVC URL重写与优化(进阶篇)-继承RouteBase玩转URL 引言-- 在初级篇中,我们 ...
- Asp.net实现URL重写
原文:Asp.net实现URL重写 [概述] URL重写就是首先获得一个进入的URL请求然后把它重新写成网站可以处理的另一个URL的过程.重写URL是非常有用的一个功能,因为它可以让你提高搜索引擎阅读 ...
- ASP.NET MVC URL重写与优化(初级篇)-使用Global路由表定制URL
ASP.NET MVC URL重写与优化(初级篇)-使用Global路由表定制URL 引言--- 在现今搜索引擎制霸天下的时代,我们不得不做一些东西来讨好爬虫,进而提示网站的排名来博得一个看得过去的流 ...
- ASP.NET Core URL Rewrite中间件
URL重写是基于一个或多个预置规则修改请求URL的行为.URL重写在资源位置和访问地址之间创建了一种抽象,这样二者之间就减少了紧密的联系.URL重写有多种适用的场景: 临时或永久移动或替换服务器资源, ...
- ASP.NET MVC URL重写与优化(进阶篇)-继承RouteBase玩转URL
http://www.cnblogs.com/John-Connor/archive/2012/05/03/2478821.html 引言-- 在初级篇中,我们介绍了如何利用基于ASP.NET MVC ...
- [转载]ASP.NET MVC URL重写与优化(进阶篇)-继承RouteBase玩转URL
引言-- 在初级篇中,我们介绍了如何利用基于ASP.NET MVC的Web程序中的Global文件来简单的重写路由.也介绍了它本身的局限性-依赖于路由信息中的键值对: 如果键值对中没有的值,我们无法将 ...
随机推荐
- Java Lambda详解
Lambda表达式是JDK 8开始后的一种新语法形式. 作用:简化匿名内部类的代码写法 简化格式 (匿名内部类被重写方法的形参列表) -> { 重写方法 } Lambda表达式只能简化函数式接口 ...
- 遇到问题之“postman报Unsupported Media Type: Content type 'text/plain;charset=UTF-8' not supported”
postman报Unsupported Media Type: Content type 'text/plain;charset=UTF-8' not supported postman之所以报Uns ...
- keil Uvision4 面向51单片机数据类型属性一览表
- 一个用于学习的react项目
React-element 根据开源项目 vue-sell进行的开发,将其改造成了react的项目.在开始学习vue的时候就是用的这个项目,发现效果不错,所以在学习React也使用了此项目. 目的:将 ...
- H5新增API
H5新增API 选择器 querySelector()和querySelectorAll(),参数都是css选择器,前者返回符合条件的第一个匹配的元素,如果没有则返回Null,后者返回符合筛选条件的所 ...
- Java将字符串的首字母转换大小写
//首字母转小写public static String toLowerCaseFirstOne(String s){ if(Character.isLowerCase(s.charAt(0))) ...
- <!--[if IE]><style></style><![endif]-->
CSS hack就是为了让你的CSS代码兼容不同的浏览器,其中最难对付的就是IE浏览器的兼容性,因为它的版本很多,不过还好,微软发表声明已经不对IE8以下的版本进行维护了.但是我们也不能就认为不用学I ...
- Ncrystal Skill设计
在使用allegro时一般都会听说过skill,使用合适的Skill会使事情事半功倍.但是现阶段所能看到的个人白嫖的Skill都有一些通病.所以我才开发符合自己操作习惯的Skill. 当前我们所能找的 ...
- YC-Framework版本更新:V1.0.6
分布式微服务框架:YC-Framework版本更新V1.0.6!!! 本文主要内容: V1.0.6版本更新主要内容 V1.0.6版本更新主要内容介绍 一.V1.0.6版本更新主要内容 1.系统例子覆盖 ...
- Vue基础开发入门之简单语法知识梳理(思维导图详解)
基于个人写的以下关于Vue框架基础学习的三篇随笔,在此基础上,做一个阶段性的知识总结,以此来检验自己对Vue这一段时间学习的成果,内容不多,但很值得一看.(思维导图详解)