凌晨三点的 URL
凌晨 3 点,一个 URL 被浏览器扔进了网络。睡了一觉醒来,怎么就到服务器了?这一路到底发生了什么?
苏醒
虽说现在是凌晨 3 点,但 breeze.vin 所在的服务器还是收到了一个请求:https://breeze.vin。警报一响,睡梦中的服务器冷不防打了个激灵。
“快告诉我,你的传输协议是什么?”
“咦?你是在问我吗?” 刚被送到这儿的 URL 回答道。
“这里只有你一个,难不成我问空气?哦这里空气是比较稀薄,你还好吧?” 服务器见 URL 迷迷糊糊的样子问道。
“我是谁,我在哪里?” 刚睡醒的 URL 有点失忆。
“你是一个 URL,这是我的地盘,刚被网卡送到这,都忘了吗?”
“哦,对!我是一个 URL,大约 10 毫秒前被浏览器创建并送出,终于到你这儿了。这是我的协议:HTTP。” 经历了一次长眠后,URL 终于想起了自己的使命——去服务器取回一张网页。
“好,HTTP 服务,你过来一下,这里有你的请求,快来领走。” 得知协议后,服务器向 HTTP 服务喊道,语气里显出几分不耐烦,可能是 URL 的短暂失忆惹他生气了。
“赶紧的,起来干活了,这么早就有请求过来了,还让不让人休息了。” 服务器在 HTTP 服务没过来之前,又咕哝了一句。
URL 在一旁瑟瑟发抖,只希望 HTTP 服务早点过来。过了不久,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 就此消失。