短地址原理
简介
一个同事遇到一个问题,他说受限于第三方的服务,自己请求所带过去的字符串因为太长,无法从第三方服务获取信息,很是苦恼😴。后来我们商量了一下,最终借鉴短地址的思想解决了问题。道理很简单,因为我们请求中的附加字符串信息第三方服务只是透传回来给我们,我们只需要把这些附加信息进行字符压缩就可以了,这样请求带过去的字符串长度就满足了要求😊。
无论是写文章还是制作一些表格的时候,我会时常用到短地址。短地址的优势在于其短(字符少)、简洁,方便书写又不占位置。方便在社交网络和第三方平台上分享链接,投放广告。比如有人会在发朋友圈的时候带上短地址,还有一些营销短信里面也会带一些短地址链接。
有现成的短地址生成器,常用的短地址转换有 百度短网址转换、Google短网址转换 和 新浪短地址转换,可惜的是谷歌关闭了该服务,官方发言如下:
1 | On March 30, 2018, we turned down support for goo.gl URL shortener. |
我经常使用百度的短地址服务,在国内访问它是最快的也能满足我的工作和学习需求,它也提供 API 服务可以参考 短网址生成接口文档 学习和了解。
我们先来了解一下 HTTP 协议中那些重定向的事。
HTTP 请求重定向
HTTP 中的 301
、302
、303
、307
、308
响应状态码,都表示重定向的响应。
其中,301
、308
响应状态码表示永久重定向,302
、303
、307
表示临时重定向。
那我们来说一下什么是重定向?
重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置(如:网页重定向、域名的重定向、路由选择的变化也是对数据报文经由路径的一种重定向)。
举个例子,你要去 A 机构办理一个证件,等你去了之后A机构的某人告诉你他们不再受理此事了,需要你去 B 机构办理,然后你就自己去了 B 机构。这个过程就类似于重定向。
那么,HTTP 协议中定义的这些30X响应状态码就好比 A机构的某人
它们告诉客户端,你需要访问另外一个地址了。
重定向做了两次 HTTP 请求, 第一次,客户端请求 A 服务器,A 响应告诉浏览器,你应该去 B 服务器访问。此时就去访问服务器 B,这个时候你可以看到浏览器中的网址变了,这就是第二次 HTTP 请求。
重定向过程:
Step-1、浏览器(客户端)发送 HTTP 请求;
Step-2、Web服务器A接收后发送 302
状态码响应,并在响应头中把对应的 Location
给浏览器;
Step-3、浏览器收到服务器返回的 302
响应码,就自动再发送一个新的 HTTP 请求(请求URL是新的 Location
中的地址);
Step-4、Web服务器(可能是 A 也可能是其他服务器)根据此请求寻找资源并发送给浏览器,最终展示给用户。
关于 Location
可以看下面的截图(这是一个重定向的 HTTP 请求示例),它是被放在响应头中的,其值是需要重定向的网址 http://www.veryitman.com
,从这个过程来看可以看出重定向是客户端(浏览器)行为。
还有个叫转发的技术,这个和重定向是不一样的,转发是服务器行为,还拿上面的 A 机构例子来说,你要去 A 机构办理一个证件,等你去了之后 A 机构的某人告诉你他们不再受理此事了,但是 A 机构可以自己协调资源帮你完成而不需要你去其他机构办理了。这个过程就类似于转发。
模拟重定向
现在使用 SpringBoot 模拟一下重定向,我用的 SpringBoot 是 2.2.0.RELEASE
版本。
①、新建 SpringBoot Web 工程,可以参考 微服务-想办法让项目运行起来 这篇文章。
②、修改 pom 文件,增加 fastjson
,示例如下:
1 | <dependency> |
③、新建 MSTestRedirectController
文件,源码如下:
1 | import com.alibaba.fastjson.JSON; |
这里要注意几个问题:
既然是重定向,该 Controller 不能使用
@RestController
注解而要使用@Controller
注解;这里使用了关键字
redirect
实现重定向;
④、启动工程,并在浏览器访问下面的网址
1 | http://localhost:8080/testredirect/access/web |
可以看到浏览器发生了重定向,截图如下:
除了上面的方法可以实现重定向外还可使用 HttpServletResponse
的 sendRedirect
方法,示例如下:
1 |
|
请求短地址过程
我拿网址 http://www.veryitman.com/
来举实例,使用百度短地址服务。
在 百度短地址页面 去生成 http://www.veryitman.com/
对应的短地址,如下图所示:
得到短地址是 https://dwz.cn/hnmau4Zs
复制该地址拷贝到浏览器(我用的是 Chrome 浏览器)的地址栏中,并打开 Chrome 的审查视图。切换到 Network 选项,此时回车打开短网址。
HTTP 发送了 GET 请求(红色1),请求地址是 https://dwz.cn/hnmau4Zs
,服务器(百度的短地址服务)返回给 Chrome 浏览器 302
状态码,浏览器发现是该重定向码就再次用 Location
里面包含的地址发送了第二次请求即重定向请求。
你也可以使用微博的短地址服务,提醒一点,微博的短地址请求返回码是 301
而百度返回的是 302
响应码。302
状态码允许各种各样的重定向,一般情况下都会实现为到 GET 的重定向,但是不能确保 POST 会重定向为 POST,302
表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B;而 301
状态码表明目标资源被永久的移动到了一个新的 URI,任何未来对这个资源的引用都应该使用新的 URI。
短地址原理
刚开始我很好奇,为什么我把长地址 A 转换为短地址 B,然后用 B 去访问居然还是 A 地址的内容,浏览器是怎么做到的?
通过上面的请求过程示例,相信大家应该大概理解了请求短地址的原理了。
在百度短地址服务中,我们将 http://www.veryitman.com/
转换为 https://dwz.cn/hnmau4Zs
,此时百度短地址服务维持了 短-长
地址的映射关系了而且是唯一的,当我们去访问 https://dwz.cn/hnmau4Zs
,其实请求的是百度短地址服务,该服务将短地址对应的长地址(放在响应头的 Location
中)返回给我们的浏览器,并返回 302 状态码,此时浏览器就重定向到了 http://www.veryitman.com/
这个网址上了。
简单总结一下其步骤如下:
Step-1、用户在浏览器里输入 https://dwz.cn/hnmau4Zs
这个网址去访问;
Step-2、浏览器解析 DNS,获取该域名对应的 IP 地址;
Step-3、获取到 IP 后,浏览器发送 HTTP GET 请求查询 hnmau4Zs
并获取到 https://dwz.cn/hnmau4Zs
对应的长地址;
Step-4、HTTP 通过 302
状态码转到去请求对应的长地址 http://www.veryitman.com/
上面了。
我把 http://www.veryitman.com/
放到百度和微博的短地址生成分别是:
1 | // 百度短地址 |
1 | // 微博段地址 |
可以看出百度生成较复杂,首先协议变成了 HTTPS
,其次生成代码是 8 位(hnmau4Zs
),而微博生成的是 4 位(aMtD
)代码。
短地址码一般都是由26个大写字母 A-Z
、26个小写字母 a-z
和10个数字 0-9
共62个字符随机组合而成,那么可以这样来生成短地址码,我们定义一个62进制,把这62个字符按照10进制数转成62进制数,那么就可以得到每个字符对应的62进制数了。同理,将短地址还原的时候把62进制转换为对应的10进制就可以了。
根据上面算法,可以看出百度可以支持 62^8 个短地址,微博可以支持 62^4 个短地址。
关于短地址生成的算法,大家可以用SpringBoot自己撸一个或者去网上找找别人已经实现的。
活着不是靠泪水搏取同情,而是靠汗水获得掌声~