前言
其实CF系列教程我原本想在第九部"Zero Trust"就结束的,毕竟在易经中,九被称为“大数”,表示天地之间最大、最圆满的数字,所谓九重天、九九归一、九九八十一难等等,因此,在第九部结束,乃是暗合天意,也显得我很有文化~。
但是,关于CF提供的多种重定向方式,确实还是很有价值的,特别是"重定向规则"后来推出的"动态重定向",能使用函数表达式灵活的构造跳转目标的URL,这和"页面规则"的重定向功能(支持通配符及基于通配符的捕获组)配合,又能玩出不少花样来了,所以想了想,忍住了在第九部结束的冲动,还是写了这第十部作为CF系列教程的最终章。
不过,在"十"结束也不差,佛教中有"九天十地"的说法(十地代表佛教中修行者境界),第十地“法云地”的菩萨,已经具足圆满智慧、慈悲和一切善巧方便,距离成佛仅有一步之遥。
刚好我研究过"般若波罗蜜多心经"和"金刚经",在"十"结束,乃是与我佛有缘~。
另:不知道还有多少人记得"九天十地,十九人魔"?
什么是重定向(HTTP重定向)?
重定向(Redirect是指在访问一个网页或资源时,将用户自动引导到另一个指定的网页或资源的过程。重定向通常发生在以下几种场景中:
- URL变更:当网站的页面地址发生改变时,重定向可以确保旧URL仍然能够访问,并将用户引导至新的URL,以避免断链和不良用户体验。
- 域名转移:如果站点更换了域名,通过重定向可以将旧域名的流量无缝转移到新域名,保持网站访问的连续性。
- 移动端优化:根据用户设备类型(如移动设备和桌面设备)进行重定向,提供优化的页面版本。
- SEO优化:当页面内容合并或者删除时,使用重定向可以集中权重,避免产生重复内容,优化搜索引擎的排名。
常见的重定向类型:
• 301重定向(永久重定向):表示页面永久搬迁到新地址。搜索引擎会将旧地址的权重传递到新地址。
• 302重定向(临时重定向):表示页面暂时搬迁,未来可能会返回旧地址,搜索引擎不传递权重。
注:除了常用的301、302之外,还有303、307、308以及特殊重定向,不过这些对于一般的朋友较少遇到,所以本文中不多讲。
CF的重定向实现方式
CF的重定向功能有几种不同的实现方式,其中最重要的是:页面规则实现的重定向以及重定向规则。
页面规则实现的重定向
在我讲Cache Rules(缓存规则)时(参见:家庭数据中心系列 cloudflare教程(六) CF Cache Rules(缓存规则)功能介绍及详细配置教程),也提到了页面规则,因为页面规则也可以实现缓存(只能基于URL方式来匹配)。同样的道理,页面规则也能实现重定向,只不过同样只能基于URL来匹配,且只能实现301或者302重定向(当然,一般也只需用到301或者302)。
页面规则的配置很简单,以将tangwudi.com
的访问重定向到www.tangwudi.com
为例:
虽然只能基于URL来匹配,但是通过页面规则实现的重定向有特有的优势:匹配传入URL时支持*
通配符及可以通过"$数字"的捕获组直接把内容传递到重定向URL,如下图:
还支持通过多个通配符+捕获组来传递参数,如下图:
不过,使用珍贵的只有3个免费名额的页面规则来做重定向,是个比较奢侈的行为~,即便要用也要最高效的使用。
使用页面规则来做重定向有个最大的优势,其在流量序列(流量序列的详细概念参见文章:家庭数据中心系列 cloudflare教程(二) CF整体方案流量序列中各技术节点功能简介)中的优先级非常高,高于后面要讲的"重定向规则"(以及"Cache Rules"):
这点非常重要,也是后面要讲的某个场景中,复杂的重定向需求能够实现的关键。
重定向规则
重定向规则介绍
由于页面规则只有3条免费的额度,并且只能通过URL这种粗旷的方式来匹配入向的URL请求,所以并不适合作为日常重定向需求的常规手段。
作为替代,CF提供了重定向规则作为日常重定向的常规手段(类似于页面规则实现的缓存功能与缓存规则之间的关系)。
注:重定向规则可以创建简单的 301(永久重定向)或302(临时重定向)规则(其实还有303、307、308重定向,比页面规则支持的类型多):
重定向规则的类型
重定向规则按照类型分为"静态"和"动态"两种,静态重定向和动态重定向各有不同的用处,适用于不同的场景。
1. 静态重定向:
• 用途:静态重定向适用于将固定的 URL 重定向到另一个固定的 URL(例如前面例子中将对https://tangwudi.com
的所有访问重定向到https://www.tangwudi.com
),这种重定向规则是静态的,因为它不会根据请求的内容、参数等动态变化,而如果要求包含参数,比如要求https://tangwudi.com/*
的所有访问重定向到https://www.tangwudi.com/*
就不能用静态重定向了。
• 典型场景:旧页面迁移到新页面、将非首选域名重定向到首选域名(上面的案例)、解决死链,避免 404 错误。
2. 动态重定向:
• 用途:动态重定向根据请求的内容、查询参数、用户地理位置等进行动态变化。例如,可以根据用户所在的国家重定向到不同的域名,或者根据 URL 中的某些参数进行重定向。
• 典型场景:基于用户的地理位置和设备类型或浏览器类型进行个性化重定向、基于请求的特定条件(如用户设备、来源国家等)定义重定向规则、基于原有域名的某种"规律"进行重定向。
重定向规则配置场景
静态重定向
常规使用场景
还是以前面的例子来举例:将tangwudi.com
的访问重定向到www.tangwudi.com
,按照如下方式配置该需求。
在"规则"-"重定向规则"-"创建规则":
当然,"当传入请求匹配时"的条件设置可以非常灵活,除了主机名还有其他很多选项:
所以,"重定向规则"和仅靠URL为匹配条件的"页面规则"比起来,能够实现灵活得多的匹配条件。
当然,鱼和熊掌不能兼得,重定向规则的匹配条件也有缺点:不支持页面规则传入匹配条件支持的*
通配符,所以导致静态重定向不能像页面规则的重定向那样通过通配符传递参数:静态重定向不管传入URLtangwudi.com/
后面带有多少参数,都只能固定跳转到www.tangwudi.com/
,既首页。
进阶使用场景:批量重定向
因为静态重定向一次只能跳转一条目标URL,如果有大量的URL要跳转(比如站点整体迁移到另一个域名),默认10条额度可不使,所以,静态重定向还有个单独的加强功能"批量重定向":
先按照如下步骤创建批量重定向列表:
然后将创建的"批量重定向列表"关联到"批量重定向规则":
常见完成:
注1:批量重定向列表只有5条额度。
注2:csv官方格式如下:
example.com/contacts,https://example.net/contact-us,301,,,,
example.com/about,https://example.net/about-us,,FALSE,TRUE,,
example.com/docs,https://example.com/draft-docs,302,,TRUE
注3:批量重定向并不是本文的重点,因为自从有了动态重定向,"规律性"的重定向不管数量有多少,一条动态重定向的目标URL表达式就够了~。
动态重定向
常规使用场景:带URI内容的跳转
动态重定向相对来说就灵活多了,虽然仍旧不支持通配符,但是却可以通过规定的"字段"实现URI部分参数的传递,例如"http.request.uri.path"字段可以实现URI部分"/*
"通配符的传递效果。
比如还是上面的例子,这次我想要把tangwudi.com/*
的访问请求原封不动的重定向到www.tangwudi.com/*
上,这时就应该使用动态重定向:
重定向的目的URL表达式如下:
concat("https://www.tangwudi.com",http.request.uri.path)
附加知识:使用规定字段和函数构造表达式
规定字段
动态重定向的表达式中可以使用规定字段来自动匹配传入URL中的对应内容,举例说明:假设传入的完整URL为:https://blog.tangwudi.com/123
,此时如果表达式中有"http.host"字段,那么字段内容就是"blog.tangwudi.com";如果表达式中有"http.request.uri.path"字段,那么字段内容就是"/123"。
注:更多字段参见:动态重定向字段。
使用函数构造表达式
构造表达式的时候要注意表达式的完整性和正确性,特别要注意一些字段本身表达的内容,还是以上面的传入URLhttps://blog.tangwudi.com/123
为例,假设以"concat"函数构造的跳转目标URL的表达式如下:
concat("https://www.tangwudi.com/",http.request.uri.path)
那么,表达式的真实效果为:https://www.tangwudi.com//123
,因为"http.request.uri.path"字段代表的内容本身就是带了"/"的,加上前面双引号中字段https://www.tangwudi.com/
结尾的"/",自然就是这个样子,这肯定是不正确的,所以正确的表达式写法需要将前面双引号中的"/"去掉,如下:
concat("https://www.tangwudi.com",http.request.uri.path)
除了concat,其他较为常用的函数还有substring,lower,upper。
以substring函数为例,其意义是"从左到右提取从指定位置开始的字符串",此处的指定位置是从0开始计数,举例说明:substring(http.request.uri.path,3)的意思为从位置3开始索引字符串,假设"http.request.uri.path"的内容为:"/tangwudi/abc",那么,此处函数表达式的输出内容为"ngwudi/abc"。
注:0-/,1-t,2-a,3-n。
进阶使用场景:图床域名迁移
以我图床的图片为例,假设我想要把https://image.tangwudi.com/2023/*.png
重定向到https://abc.tangwudi.com/image/*.png
(*
的内容必须一样),新建动态重定向规则如下:
重定向目标URL表达式为:
concat("https://abc.tangwudi.com/image/",substring(http.request.uri.path,6))
注:本例中这种情况使用页面规则的重定向也简单。
高级使用场景:群站域名基于地理位置进行跳转
这是以我之前的部署方式为例子,当时我刚好处于从备案域名往"tangwudi.com"上迁移的时期,所以那段时期我2个域名同时生效,所有的应用都有2个域名入口:一个是CF的,域名"*
.tangwudi.com";一个是备案域名,域名假定是"*
.tangwudi.xyz"。
我当时的需求是所有应用对外使用统一入口"*
.tangwudi.com",但是根据访问请求的来源做判断:如果访问者是国内IP,就重定向到"*
.tangwudi.xyz/*
";如果访问者不是国内IP,则正常访问。
这个需求里有2个*
变量:三级域名的主机名和URI内容:国内用户访问blog.tangwudi.com/123
,就重定向到blog.tangwudi.xyz/123
;访问wlk.tangwudi.com/12345
,就重定向到wlk.tangwudi.xyz/12345
。
不过,这种需求就有点麻烦了,我前面提到过,就算是动态重定向,也只能通过字段"http.request.uri.path"来实现URI部分对应的"/*
"通配符传递效果。而主机名部分"http.host"只能传递完整域名(本例中是blog.tangwudi.com和wlk.tangwudi.com),无法只传递三级域名的主机名部分(本例中是blog和wlk)。
本来,如果只是无条件从"*
.tangwudi.com/*
"重定向"*
.tangwudi.xyz/*
",类似的需求一条页面规则的重定向就完事:
只是,要实现基于国家等地理位置为条件进行跳转,就必须结合重定向规则的动态重定向来完成。
咋办呢?经过一番思考:既然页面规则实现的跳转只是不支持基于地址位置判断,跳转部分可以实现;而动态重定向可以实现基于地址位置的判断,只是不能实现跳转部分的要求,那我可不可以将两部分结合在一起来实现该需求呢?
有了这个思路就好办了:
- 第1步、创建一条动态重定向规则将国内用户重定向到一个虚构的URL
通过目标表达式构造一个以虚构的域名"abc.tangwudi.com"为host的全新URL让国内用户进行重定向(虚构的域名也需要在CF的DNS里添加任意地址的解析并开启小橙云朵),同时将完整的三级域名和URI部分组合在一起作为全新URL的URI部分,以便页面规则使用通配符进行提取:
URL重定向表达式为:
concat("https://abc.tangwudi.com/",http.host,http.request.uri.path)
在上面的表达式中,使用"http.host"来传递原始的三级域名,使用"http.request.uri.path"来表示原始的URI部分,所以如果原本的访问连接是"https://blog.tangwudi.com/123
",那么该表达式构成的全新URL就是"https://abc.tangwudi.com/blog.tangwudi.com/123
"。
-
第2步、创建一条页面规则来接收国内用户对虚构URL的访问,从虚构URL中捕获相关信息以构造正确的访问URL,然后再次以重定向方式发给国内用户
利用页面规则在流量序列中优先级高于Cache Rules的优势(该重定向不能被缓存),接收国内客户端使用全新URL发起的访问,然后使用前面讲过的通配符捕获组来分离URL中URI部分包含的主机名和原来的URI内容,组成了第2次重定向URL:"
https://blog.tangwudi.xyz/123
",并发给了国内用户。
-
第3步、国内用户使用第2次收到的真正的URL"
https://blog.tangwudi.xyz/123
"进行访问。
这样,经过了2次重定向,实现了我基于地理位置和2个变量进行重定向的要求。不过,我其实并不建议正常情况下使用方式,因为这种方式有个很大的缺点:跳来跳去,给人观感不好,会显得网站很不专业(个人观感)。
注:我这里只是简单的演示了2个不算太复杂的例子,实际情况下更复杂的需求很多,就看大家对动态重定向的表达式以及页面规则通配符的理解和想象力了。
其他重定向方式
其实,除了使用页面规则、重定向规则实现来重定向功能以外,使用worker也可以实现,只不过,鉴于worker这个万金油地位(好多功能都可以用worker实现),我就不把它算作正儿八经的重定向方式了。而且,使用worker来实现重定向有个最大的麻烦:worker优先级在流量序列中最低,所以为了保证访问请求能够到达worker以实现重定向,可能需要配置其他流量序列的功能模块来配合(比如Cache Rules),这样就远不如使用重定向规则和页面规则配合完成重定向功能来得省心。
另:在"转换规则"中,还有一个"重写URL"的功能:
如果说"重定向"是"正大光明"的告诉用户改变访问地址,那么"重写URL"就是"偷偷摸摸"的在不告诉用户的情况下(浏览器访问地址不会变化)把访问URL的URI部分修改了(域名改不了),不过这和本文"重定向"的主题不符,我就不多说了。
注:国内CDN只提供"重写URL"功能(可能是怕大家干坏事),所以当需要域名重定向功能时,很多朋友不得不使用自己的VPS来实现跳转(我之前备案域名实现跳转www就是使用腾讯云轻量服务器上的nginx来完成),从这个角度来说,CF免费提供的各种强大的基于边缘网络的重定向功能可真是太良心了,让我们不再需要动不动就在VPS上配置(关键很多将自己静态网站进行托管的人都没有自己的VPS~),再次盛赞一下大善人。
结束感悟
CF系列教程终于写完了(从7月10号发布第一部,到9月2号的第十部,期间将近2个月的时间),每一部我都写得很累(包括这最后一部我原本认为写起来会很轻松的"重定向"),关键就在于CF相关知识的延伸性:写着写着随时可能蹦一个我都没太关注的概念出来(如果只是配置功能,不写成文章,也不会去关注这些概念),导致我不得不频繁使用"注"或者"附加知识"的方式进行临时性的解释,否则文章的可读性就要被破坏,再加上本来CF很多功能相互都有关联性,所以导致我写每一部教程都非常累。
不过,虽说是如此,我觉得还是很值得的,现在回头来看没写系列教程之前的我,对每一部教程讲述的功能,理解得都较肤浅,只是停留在能够应付基本使用的层次上,所以导致印象也不深刻。比如本篇教程的重定向功能,我甚至都忘记了当时从备案域名迁移到"tangwudi.com"时具体是怎么配置的了(毕竟大半年前迁移完之后我就没怎么使用过复杂的重定向功能了),研究了半天才找到关键点(这就是不形成文字记录的下场)。而现在,当这篇教程写下来之后,即使我以后又忘记了,只要看看这篇教程,就什么都想起来了,这就是俗话所说的:好记性不如烂笔头。
不过,CF系列教程所讲述的内容,只是基于我日常使用习惯,将我认为常用的功能进行了归纳和总结,而在我的"日常使用习惯"形成的盲区之外,还有太多的功能没谈到,比如"点"类型的"Hotlink保护"功能,打开默认就可以防止图片盗链(基于referer判断):
或者"面"类型的"D1数据库",也有免费计划可以蹭的:
只不过因为目前我的知识面有限,有些功能想蹭都不知道怎么去蹭,只能留下遗憾在心间了,如果以后知道方法了,再用文章写出来吧,不过就不是以系列教程的名义了,毕竟,不能破坏"十"全"十"美。
另:所谓"言必信,行必果",终于把系列教程写完了,强迫症患者总算可以睡个安稳觉了: