凌晨三点的 URL
凌晨 3 点,一个 URL 被浏览器扔进了网络。睡了一觉醒来,怎么就到服务器了?这一路到底发生了什么?
苏醒
虽说现在是凌晨 3 点,但 breeze.vin 所在的服务器还是收到了一个请求:https://breeze.vin。警报一响,睡梦中的服务器冷不防打了个激灵。
“快告诉我,你的传输协议是什么?”
“咦?你是在问我吗?” 刚被送到这儿的 URL 回答道。
“这里只有你一个,难不成我问空气?哦这里空气是比较稀薄,你还好吧?” 服务器见 URL 迷迷糊糊的样子问道。
“我是谁,我在哪里?” 刚睡醒的 URL 有点失忆。
“你是一个 URL,这是我的地盘,刚被网卡送到这,都忘了吗?”
“哦,对!我是一个 URL,大约 10 毫秒前被浏览器创建并送出,终于到你这儿了。这是我的协议:HTTP。” 经历了一次长眠后,URL 终于想起了自己的使命——去服务器取回一张网页。
“好,HTTP 服务,你过来一下,这里有你的请求,快来领走。” 得知协议后,服务器向自己的 HTTP 服务喊道,语气里显出几分不耐烦,可能是 URL 的短暂失忆惹他生气了。
“赶紧的,起来干活了,这么早就有请求过来了,还让不让人休息了。” HTTP 服务还没过来,服务器又咕哝了一句。
URL 在一旁瑟瑟发抖,只希望 HTTP 服务早点过来。过了不久,对方终于出现了。
“快点,跟我过来!” HTTP 服务也没好气地说道。
使命
URL 跟着 HTTP 服务来到一个陌生的房间,里面高高挂着 80、443、8080、8000 四块牌子。
“你端口号是多少?”
URL 摸了摸口袋,竟然找不到端口号,心中一虚,吞吞吐吐地说:
“那个,我好像没有端口号。”
“没有就没有。” 看到 URL 吞吞吐吐的样子,HTTP 服务更不耐烦了,但手上的动作没停,狠狠拉了一下 80 的牌子,然后头也不回地走了。
“来了,来了。” 80 牌子的另一头响起一个略微耳熟的声音,不一会儿便来了一个人。
虽说看起来有点陌生,但 URL 还是看到了熟悉的身影,赶忙过去打了声招呼。
“Hi JavaScript 你怎么也在这啊?”
“咦?你是谁,你怎么认识我?”
突然间,URL 想起这是服务器,眼前的这位不可能是自己认识的那个人。
“我认识一个长得很像你的人,他住在浏览器里。我刚从那边过来。”
“哦~ 那是我哥。我和他不熟。”
“emmm...”
“把查询参数给我,我需要处理一下。” 服务器上的 JavaScript 看着 URL 尴尬的样子说道。
一摸口袋,又是啥也没有。只能说道:“我这没有。”
“不要紧张,没有就不用处理了,还能偷个懒。”
URL 松了口气。
“接下来,把资源路径给我吧,我帮你去拿。”
一摸口袋,有点发虚:“我这也没有请求内容。”
“路径是 / 啊。文件读取小弟过来一下,按服务器的路由配置取出首页内容。” JavaScript 利落地说道。
“好嘞!稍等,马上好!” 一旁的小弟说道。
对于这一幕,URL 早已见怪不怪了。浏览器里那位做哥哥的也一样,总是使唤小弟干这干那,自己只负责处理小弟交回来的结果。趁着小弟忙活,URL 问了一句:
“服务器的生活环境怎么样?”
“环境稳定、API 丰富、资源充足,关键是我还能访问不少系统能力。小弟说来就来,个个身怀绝技,简直是天堂。不像浏览器,限制可多了,真替我哥感到惋惜……”
“大哥,您要的数据已经准备好了。” 说话间,小弟带着一箱箱数据跑了过来。
“好的,你先去忙吧。”
“呐,这是你要的东西,就是下次别这么早了,身体要紧。我要去睡个回笼觉了,再见~” 熟人的态度就是不一样。
“哦,对了,那边有个传送门,进去你就回到你诞生的地方了。” JavaScript 补充道。
顺着提示,URL 走向传送门。伴随着阵阵眩晕,又一次进入了休眠状态。
回归
浏览器一盆冷水把 URL 泼醒。
“呀,你终于回来啦,快把页面给我,用户已经快等不及了。”
“你……” 抱怨还没来得及出口,浏览器已经一头扎进一旁的箱子里,不管不问了。
URL 静静地待在一旁,知道自己的使命已经结束。
新同事
不知不觉到了 4 点,URL 旁边突然多了一个同类——一个刚刚诞生的新 URL,正手忙脚乱地整理着满箱包裹。
“前辈前辈!” 新 URL 凑了过来,“马上就要出发了,我有点紧张。你跑过一趟,快给我讲讲,身上这些口袋都是干嘛的?”
“别慌。” 老 URL 坐起身,从怀里掏出一张皱巴巴的纸,“诺,出厂说明书,咱们的完整形式就长这样:”
<scheme>://<userinfo>@<host>:<port>/<path>?<query>#<fragment>
“emmmm... 看起来是有点晕?”
“定义总归是高度概括的。记住两条:由 <> 包裹的是咱们的组成部分,就像一个个装着具体信息的口袋;其他字符是分隔符,用来划分这些口袋。”
“那每个口袋都装什么呀?”
“一个个说。” 老 URL 指着纸上的第一格。
“scheme,学名方案,也常被称为协议。告诉浏览器应当使用哪种方式访问资源,例如 http、https。在绝对 URL 中,这一部分不可缺少。”
“userinfo,用户信息,可以携带用户名等身份信息。如今网页很少使用这种写法,敏感凭据也不应放在 URL 中。没有 userinfo 时,后面的 @ 也不会出现。”
“host,主机名。网络投递员会根据它把咱们投递到对应的服务器。”
“port,端口号,指定目标服务的端口。省略时会使用当前方案的默认端口,例如 HTTP 通常为 80,HTTPS 通常为 443。刚才我就没带端口,人家直接按 80 给我处理了。”
“path,路径,标识目标资源在服务器中的位置。服务器会根据路由或文件映射规则处理它。”
“query,查询参数,向服务器补充一组参数。通常由键值对组成,并使用 & 分隔。”
“最后是 fragment,学名片段,也常被称为锚点或 hash。它只在客户端使用,浏览器发送 HTTP 请求时不会把它交给服务器。它可以定位页面中的元素,也常被前端路由使用。”
“哇,原来每个口袋都有讲究!” 新 URL 眼睛亮了起来。
“那当然,咱们可是千千万万个字符串中比较帅的那一个。” 老 URL 得意地拍了拍胸脯。
销毁
出发前,老 URL 仔细瞧了瞧新 URL 的包裹,里面的数据竟然写着一个大大的标题——《凌晨三点的 URL》。自己的故事?哈哈!
不久后,新 URL 载着一个大大的 OK 回到浏览器。老 URL 还没来得及道贺,浏览器便被关闭了。眼前一黑,两个 URL 就此消失。