【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文件来简单的重写路由.也介绍了它本身的局限性-依赖于路由信息中的键值对: 如果键值对中没有的值,我们无法将 ...
随机推荐
- Idea学习之"使用SVN如何查看哪一行是哪一个人写的历史日志"
点击出的方法 结果图 点击记录,显示详细
- web app遇到的一些坑及小技能(持续更新...)
遇到的一些坑 问题:手机端 click 事件会有大约 300ms 的延迟 原因:手机端事件 touchstart --\> touchmove --> touchend or touchc ...
- web入门+书籍推荐
如果你想建立一个自己的网站,你可以从网上搜到许多的教程:比如 wordpress gitpages 等等. 如果你想了解这个框架是怎么工作的,你可以了解以下下面的三个基本概念: 服务器, 数据库, 前 ...
- potoshop cs6安装配置16错误解决办法(win10系统)
问题截图如下: 解决方法: 右击图标选择属性:选择兼容性-->兼容模式-->以管理员身份运行-->应用 然后就可以打开了!
- 腾讯云服务nginx部署静态项目
一直想要搭建自己的blog,买了基础云服务器练手 文章内容是根据腾讯文档(https://cloud.tencent.com/document/product/213/2131)总结 部署静态页面归纳 ...
- 『现学现忘』Git基础 — 1、版本控制系统介绍
在具体了解Git之前,首先需要我们了解一下VCS,即版本控制系统(version control system) 1.什么是版本控制系统 版本控制是一种记录一个或若干个文件内容变化,以便将来查阅特定版 ...
- Mysql 8 使用过程中的命令记录
Mysql 8 使用过程中的命令记录 注: 当前 MySQL 数据库的版本 8.0.27 修改密码 1. 使用其他用户修改root 密码 ALTER USER 'root'@'localhost' I ...
- linux centos 8.2 安装docker
1 使用yum -y install docker安装后启动docker提示Failed to start docker.service: Unit docker.service not found. ...
- 基于Composer的Laravel扩展包开发工作流 ,实现laravle项目的文件管理(记录成长)
PHP Composer包开发 基于Composer的Laravel扩展包开发工作流 实现laravle项目的文件管理,添加文件/文件夹,删除文件,查看代码/文件(代码支持缩进,支持语法高亮) com ...
- 几个i的幂的累加公式1^2+2^2+3^2 2~5
1^2+2^2+3^2+--+n^2=n(n+1)(2n+1)/6 1^3+2^3+3^3+...+n^3=(1+2+3+...+n)^2 =[n(n+1)/2]^2 1^4+2^4+3^4+--+n ...