原文地址
“这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战”
其实很多公司都会发送各种营销短信给用户,而且短信里面通常会带上各种活动链接,然后用户点开链接可以打开浏览器到活动页面。
发送短信的时候里面有个链接看到没?这就是短链接,然后我们把短链接复制到浏览器打开,发现跳转之后立马就换了个地址,而且链接还很长很长。先暂停一下,思考背后的原理是什么?
// 原地址
https://u.10010.cn/qAPZU
// 目标地址
'https://m.client.10010.com/mobileService/clickCountLogRecord/pageClickCount.htm?flag=new&title=礼包&openUrl=https://m.client.10010.com/myPrizeForActivity/tenth517/homePage&duanlianjieabc=qAPZU'
短链接跳转长链接,其实原理很简单,通过 302 临时重定向即可完成。
- 浏览器先向 u.10010.cn/qAPZU 地址发送 GET 请求。
- 根据参数 qAPZU 去查找数据库,找到对应的活动的真实链接。
- 后端返回了 302 重定向,并且指定了目标地址。
- 浏览器跳转到目标地址。
下面是用 node 代码简单实现一个重定向的功能。
const http = require('http')
const server = http.createServer()
// 这里存放所有的短链和长链的对应关系
const urlMap = {
'qAPZU': 'https://m.client.10010.com/mobileService/clickCountLogRecord/pageClickCount.htm?flag=new&title=礼包&openUrl=https://m.client.10010.com/myPrizeForActivity/tenth517/homePage&duanlianjieabc=qAPZU'
}
server.on('request', function (req, res) {
const pathname = req.url.slice(1)
const taretUrl = urlMap[pathname]
console.log(taretUrl)
if (taretUrl) {
// 通过响应头来实现服务端重定向
res.writeHead(302, {
'Location': encodeURI(taretUrl)
})
res.end()
} else {
res.end('404')
}
})
server.listen(3000, function () { console.log('启用成功'); })
常见问题
如何实现长地址和短地址的对应关系呢?首先我们需要确保每次生成的短地址都是唯一的,因此我们很容易想到随机数,随机生成第一短地址,去查找是否用过,用过就再随机,如此往复,直到随机到一个没用过的短地址。
上面是典型的错误回答,下面咱们直接说正确的原理。正确的原理就是通过发号策略,给每一个过来的长地址,发一个号即可,小型系统直接用 mysql 的自增索引就搞定了。
https://u.10010.cn/1
https://u.10010.cn/2
...
https://u.10010.cn/999
其实生成的短链还有一个特点,就是不会直接用 10 进制表示,比如 u.10010.cn/999 这样的形式,而是把 999 转换为 62 进制表示,比如 u.10010.cn/g7 。其中 999 表示我发号策略参数唯一标识。
62进制是通过(数字 + 小写字母 + 大写字母)组合而成的。如果五个字符是(0-9)、(A-Z)、(a-z),那5位字符可以穷举多个呢?62^5 = 916132832个 如果6位呢?62^6 = 56800235584个 500多亿个网址。
微信防封禁
小程序提供的服务中,不得存在滥用分享违规行为。但是有时候我们只是普通的分享也有可能被微信封禁,脑瓜子嗡嗡的,无缘无故就被封封禁了。
假设我有两个页面,一个是首页,一个是活动页面。
https://u.10010.cn/1
https://u.10010.cn/2
...
https://u.10010.cn/999
当活动页面 pages/activity/activity 分享的时候,我们不是直接分享这个页面,而是分享首页 pages/index/index。但是直接到首页肯定是不行的呀,我们要加个参数标记一下 pages/index/index?channel=qAPZU
这个时候分享再打开我们发现有参数 channel=qAPZU,然后 API 后端会提供给我们一个解析参数的接口,后台通过查询数据库返回我们真实地址是 pages/activity/activity,最后我们跳转到目标页面。
这样一来每次打开的是首页,通常首页是不会封禁,然后才会跳转目标页面。
如果还是很担心首页被封禁,我们可以多准备几个首页就可以,比如一个是为营销活动做的首页,一个是正常的首页。
{
"pages": ["pages/index/index", "pages/index2/index", "pages/activity/activity"]
}
我们选择备份的首页跳转 pages/index2/index?channel=qAPZU,如果 index2 封了不影响我们其他业务。
如果发现活动地址 pages/activity/activity 被封了怎么办?我们可以 channel=qAPZU 对应的地址改成另一个活动页面,如果你实在没有其他活动页面了,你就改成首页也行,防止用户在封禁过程中用户打开的是空白页面。
你可以打开某多多试一试,他们的活动也是先到首页再到目标活动页面
当然,站在巨人的肩膀上还是要按照规矩办事,必须遵守平台规则。