url重写规则
打开浏览器,重则地址栏里那串东西叫URL。写规多数人只把它当门牌号,重则点进去就行。写规但服务器收到这串字符之后,重则往往不是写规直接去找那个文件,而是重则先拿它去比对一张表——这张表就是重写规则。你看到的写规干净链接,背后八成有它在干活。重则
我第一次认真翻重写规则,写规是重则因为一个客户的网站突然大量404。他换了服务器,写规旧站是重则动态的,链接长这样:product.php?写规cat=12&id=305。新站用静态页面,重则路径是/product/305/。搜索引擎里收录的全是旧的。他不想丢流量,就得让服务器在收到旧链接时,悄悄把内容指向新地址,同时告诉浏览器“这东西永久搬家了”。这活儿,就是重写规则干的。
Apache下面,规则写在.htaccess文件里,语法核心是RewriteRule。比如把旧动态链接转到新静态路径,大概长这样:
RewriteEngine On RewriteCond %{ QUERY_STRING} cat=12&id=([0-9]+) RewriteRule ^product\.php$ /product/%1/? [R=301,L] 这里有个坑。很多人写规则时忘了加?,结果旧链接后面的查询字符串被原样带到了新地址,变成/product/305/?cat=12&id=305。搜索引擎会认为这是两个不同页面,权重就散了。那个问号的作用是吃掉原始参数,别小看它。
Nginx的写法不一样,但思路相通。它用rewrite指令配合正则,放在server块里。比如把所有.html结尾的请求转给PHP处理:
rewrite ^/([a-z]+)\.html$ /index.php?page=$1 last; 注意那个last标志。它告诉Nginx:重写完这条规则后,重新走一遍location匹配。如果用break,就停在当前location里不再往下查。这两个标志选错,轻则规则不生效,重则死循环,服务器CPU直接飙满。我见过一个哥们儿把last写成break,结果所有页面都返回首页内容,查了一下午。
重写规则还有个隐蔽的用途:防爬虫和防盗链。有人写规则判断HTTP_REFERER,如果不是自家域名,就把图片请求重写到一个警告图或者直接返回403。这招对小型站点够用,但别指望拦住专业采集。更实际的做法是配合User-Agent做简单过滤,把明显是脚本的请求重写到空页面。
顺序很重要。规则是从上往下匹配的,一旦命中某条且带了L或last标志,后面的就不再看了。所以具体规则要写在前面,泛匹配放后面。我习惯把301跳转放最前,伪静态规则居中,防盗链和拦截放最后。这样调试起来也清楚,哪条没生效,一眼能定位。
调试是个体力活。浏览器缓存、CDN缓存、服务器缓存,三层叠在一起,改一条规则可能十分钟后才看到效果。我的笨办法是:先在本地用curl -I看响应头,确认状态码和Location对不对,再去线上验证。别一上来就刷浏览器,容易被缓存骗。
最后说个真事。有个做外贸的站,产品页URL里带中文参数,没做编码处理。重写规则里的正则匹配不到,所有中文分类页面全跳到了404。他以为是服务器问题,换了三家主机商。其实就是规则里少了个B标志——Apache里用它来转义非字母数字字符。加上之后,问题消失。重写规则这东西,细节全在那些不起眼的标志和转义符里。