我接手过一个老项目,ASP.NET Web Forms写的重写,跑在Windows Server 2016上,重写IIS 10。重写客户抱怨说,重写网站URL长得像外星代码——/Product.aspx?重写id=123&cat=5,SEO部门天天骂娘。重写我花了半小时装了URL Rewrite模块,重写改了两行web.config,重写URL变成/product/123/5。重写客户以为我施了魔法,重写其实不过是重写IIS 10自带的功能,很多人压根不知道它有多强。重写
URL重写,重写核心就一句话:把用户请求的重写URL,在服务器端偷偷换成另一个URL去处理,但浏览器地址栏不变。IIS 10里这个功能叫“URL Rewrite”,是个独立模块,默认不装。你得先去IIS管理器——网站功能视图——双击“URL Rewrite”,如果没看到,就去“服务器节点”->“管理”->“添加角色和功能”,勾选“URL Rewrite”或者直接去微软官网下载安装包。装完重启IIS,完事。
别急着写规则。先想清楚你的需求。伪静态只是最浅的一层。我做过的案例里,真正有价值的重写是这三类:
1. SEO友好URL——把查询字符串变成路径,像上面那个例子。
2. 强制HTTPS或去掉www——用一条规则搞定,别让用户输http://还能访问,搜索引擎会认为你有重复内容。
3. 反向代理或API网关——比如把/api/*直接转发到内网另一台服务器,IIS 10的Rewrite模块支持proxy动作,比ARR(Application Request Routing)轻量得多。
规则写在web.config里,结构长这样:
<rewrite> <rules> <rule name="ProductUrl" stopProcessing="true"> <match url="^product/([0-9]+)/([0-9]+)$" /> <action type="Rewrite" url="Product.aspx?id={ R:1}&cat={ R:2}" /> </rule> </rules> </rewrite>{ R:1}是正则捕获组,从1开始,不是0。写错了你会得到404,而且IIS不会给你任何提示。我调试时习惯先在本地用IIS Express跑,反正web.config通用。 有个坑必须提醒你:重写不等于重定向。Rewrite是服务器内部悄悄换URL,浏览器不知道;Redirect是告诉浏览器“你去访问另一个地址”,地址栏会变。搞混了,你可能会陷入无限循环。比如你想强制HTTPS,用Redirect(301),但如果你用Rewrite,浏览器还是请求http,服务器内部换成https处理,但响应没告诉浏览器更新地址,用户永远停在http,但内容正常——这其实也可以,但SEO不推荐。正确做法是301重定向。
再说个我踩过的雷。IIS 10默认自带“静态文件处理”和“ASP.NET”两个管道。如果你的站点是纯静态HTML,URL重写规则放在<system.webServer>节点下没问题。但如果你跑的是PHP(通过FastCGI),规则要放在<location path=".">里,否则可能不生效。具体原因涉及IIS的请求处理顺序,简单说就是PHP的handler可能先截获了请求,轮不到Rewrite模块。解决方案是给规则加上<conditions>,排除掉物理存在的文件:
<conditions> <add input="{ REQUEST_FILENAME}" matchType="IsFile" negate="true" /> </conditions>最后说个性能问题。URL重写规则是正则引擎跑的,每条规则都消耗CPU。规则少没事,但如果你写了上百条,建议用<rewriteMaps>(字典映射)代替正则。IIS 10支持内存中的rewrite map,查找速度比正则快一个数量级。我见过有人用50条正则规则做产品分类,结果压力测试下CPU飙到80%,换成rewrite map后降到15%。
别把URL重写当万能药。它解决的是URL美观和路由问题,不是安全。有人用重写隐藏真实文件路径,比如把/admin/login.aspx重写成/manage/enter——这没用,攻击者直接访问物理路径照样能打开页面。真要安全,用IP限制或身份验证模块。
IIS 10的URL重写,归根到底是个工具。别迷信图形界面里的“导入规则”向导,那玩意儿只适合Apache的.htaccess转过来,复杂逻辑还得手写。你最好熟悉正则表达式,至少会写^、$、([0-9]+)、.*?这几个。否则你会被{ R:0}和{ R:1}的区别折磨到怀疑人生。
就写到这。下次你遇到URL丑陋、跳转混乱、或者想给旧系统加个RESTful接口,先打开IIS管理器试试URL Rewrite。装个模块,写两行规则,比改代码快多了。