【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文件来简单的重写路由.也介绍了它本身的局限性-依赖于路由信息中的键值对: 如果键值对中没有的值,我们无法将 ...
随机推荐
- C++ - free()函数释放内存后的指针行为
一个指针释放后不置空的后果: free(p)之后原本那块内存的数据已经被释放了,内存重新收回.但此时的指针变量依然指向那块内存,在以后的代码中若不小心继续调用指针变量,会出现不可预料的错误. 不置空的 ...
- C语言泛型编程——泛型冒泡排序
在实际编程中,常常会需要一些方法(函数),比如排序,它们具体实现基本一致,仅仅只有参数类型不同, 那么可不可以有一种通用的函数,不管是什么类型的参数都可以通用呢? 泛型编程:泛型即是指具有在多种数据类 ...
- 手把手教你打造一个纯CSS图标库
来,干了这碗安利 写这篇文章的目的其实就是为了安利一下我的图标库:iconoo,所以,开门见山,star吧少年少妇们!(这样的我是不是应该要加个github互粉的团伙了?) 主题说完了,下面进入正题. ...
- python正则表达式替换或去除指定字符
代码: import re regEx = "[\n""|]" # 去除字符串中的换行符.中文冒号.|,需要去除什么字符就在里面写什么字符 str= re.su ...
- Android中的Preference结构的设计与实现
本文主要通过分析源代码来分享Preference的设计和实现方式,让开发者们在今后更加顺手地使用和扩展Preference类,或者在设计其他类似的界面和功能时可以提供参考帮助. Preference概 ...
- Git本地上传口令
$ cd /d/GitProject (进入要上传的文件的文件夹) $ git pull (更新本地库) $ git add . (添加 ...
- jq移动端图片预览 (fly-zomm-img.js)
效果图: ===>==> 里面还与很多属性设置: index 关闭按钮等等 代码: //html-----------------------<div class="he ...
- [ThinkPHP]2-Rce buuoj
[ThinkPHP]2-Rce 进来是这个页面 构造路径. 好,构造正确,但是服务器拦截了对该操作的访问 打开提示网站,看到关键信息 分析正则 老版本的正则可以用 '@'符号表示模式.以下正则是模式e ...
- linux压缩及解压命令
.zip文件:压缩:zip,解压:unzip 如果要解压到指定目录,可以加上 -d 选项 .gz文件:压缩:gzip,解压:gunzip 压缩.解压缩后原文件丢失,可以加上 -c 选项利用 linux ...
- Postman大势已去
作为一名前端,日常开发过程中除了写业务代码,前后端联调更是重要的一环.但这一环却往往是整个开发中最繁琐也最累人的一环.任谁都想早点下班,然而提升联调效率并不是个纯技术相关的问题,而是需要有良好工作流程 ...