大侠稍等!URL 中为什么出现奇怪的字符

为何中文名称的图片打开后网址是一串乱码?为何好好的短网址复制粘贴就变长了一大长串?罪魁祸首竟然是……html

杭州终于出梅了!二狗子看到气象台发布的消息,开心的不得了。杭州的雨从五月底一直下,天天除了雨仍是雨,天空都是灰蒙蒙的,都快把人搞抑郁了。出梅了,天晴了,二狗子的心也随着蓝天上的白云飘荡出去了。编程

同事小峰峰告诉二狗子,公司后边的皇后公园,向日葵开的正好,一大片一大片的绵延出去,阳光下金灿灿的,可好看了。“要不要一块儿去看看?你拍点照片给婷婷呗~”浏览器

二狗子一想起女神婷婷很喜欢向日葵,拍点美丽的照片,能看到婷婷甜甜的笑,就火烧眉毛地拉着小峰峰往公园跑。安全

二狗子拍了好多照片,精挑细选了好几张,上传到本身的图片网站了。他用浏览器打开图片看了看,没有问题,很是完美,就复制了图片地址发给婷婷。服务器

二狗子有点尴尬,明明在浏览器中是正常显示的 URL 地址,怎么复制出来就变成一堆奇怪的字符了呢?网络

二狗子百思不得其解,得,仍是问一下本身的存储服务商——无所不能的又拍云吧。app

客服乔巴接待了二狗子,并告诉了二狗子这个问题的由来。编程语言

URL - 网络资源定位符

经过互联网来访问网络中资源的时候,最多见就是经过浏览器输入资源的 URL 地址来进行访问。网站

URL(Uniform Resource Locator),是互联网中的一个核心概念,官方名称叫作统一资源定位符。简单的来讲,URL 就是一个由网站开发者给资源在互联网上分配的地址。通常来讲,每一个有效的 URL 都指向单独的一个资源,这个资源能够是HTML 页面、CSS 文档,又或者是一幅图像等。编码

一个 URL 由不一样的部分组成,其中一些是必须的,而另外一些是可选的。下面咱们来看下 URL 的具体组成部分:

上图就是完整的 URL 结构展现。不少时候其中的一些部分是用不到的,例如 user information。做为参考,咱们能够来看一下又拍云存储的 URL 地址。

https://www.upyun.com/product...

  • https:// ,请求协议(scheme),指定了浏览器须要使用何种协议来与目标服务器进行通信。常见的协议有 HTTP 和 HTTPS。
  • www.upyun.com,域名(host),代表请求的资源所在的服务器地址。
  • /products/file-storage ,资源路径地址(path),服务器经过路径来确认访问资源在服务器上的哪一个位置。

通常常见的 URL 地址由这三个部分组成,其他的部分根据开发的须要,能够进行自定义。

了解 URL 的概念后,就知道二狗子的图片连接 http://fileupload-upyun.test.... 的由来了。经过这个地址,婷婷能够访问到二狗子服务器上拍摄的向日葵图片。可是,为何二狗子复制了浏览器地址栏中的地址,发送给婷婷的时候,URL 却变成了 http://fileupload-upyun.test.... 了呢?

奇怪的字符 - URL 编码

咱们能够看到,二狗子发给婷婷的连接,改变了的部分属于 URL 的 path 部分,并且,英文部分其实没有改动,只有中文的部分被转成 %XX 的这种编码格式了。

虽然,这不会影响图片的打开,地址依旧是有效的。可是为何浏览器要把中文转换成这种奇怪的形式呢?

咱们先来看一个例子。若是访问下面这个 URL 连接:

https://www.baidu.com/s?wd=?#!

这是使用百度进行搜索的一个连接,/s 后面跟着的 ? 表明请求参数(query),也就是咱们想向请求的服务器提交一些参数。wd 为百度规定的查询参数名,wd 后边跟着的就是须要搜索的内容。

咱们想搜索 ?#! 这个内容,但是当你复制这个连接放在浏览器中打开时,会发现一个问题,百度仅仅是搜索了 ? 这个内容,#! 不见了。

为何呢?若是你仔细看上面那张 URL 的构成图,会发现 URL 结构中还有一个锚点(fragment)的部分,分隔符号就是 #。

因此这里就会出现一个问题,咱们的业务需求是将 # 当作一个普通文原本进行搜索,可是 # 在 URL 中有特定的意思,因此浏览器就遇到了一个解释歧义的问题。

这就引伸出一个问题,URL 在数据传递中,若是存在用做分隔符等特殊做用的保留字符怎么办?

在实际的业务场景中,会常常碰到一些在 URL 中有歧义性的数据,为了不解释错误,开发者想出了一个解决方法,就是对这些数据进行必定的处理,从而解决歧义的问题。处理的方法有不少种,最经常使用的处理方式,就是对歧义性的数据进行 URL 百分号编码。

哪些是会引发歧义的数据呢?

根据 RFC 3986(https://tools.ietf.org/html/r...)的规定,咱们能够获得下面的结果。

  • 不在 ASCII 码范围内的字符 (URL 使用 ASCII 码进行编解码)
  • ASCII 码中不可显示的字符
  • URL 中规定的保留字符
  • 不安全字符(传输环节中可能会被不正确处理),如空格、引号、尖括号等

保留字符由组件分隔符(gen-delims)和子组件分隔符(sub-delims)组成,这些字符在 URL 中都有特殊的意义:

Reserved = gen-delims / sub-delims

  • gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
  • sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

URL 中能够直接使用的非保留字符则有:

Unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"

  • ALPHA:%41 - %5A AND %61 - %7A (英文字母大写 A-Z 以及英文字小写 a-z)
  • DIGIT:%30 - %39 (数字 0-9)
  • -: %2D .: %2E _: %5F
  • ~: %7E (某些服务实现将其做为保留字符,通常也须要进行编码处理)

这下子咱们就了解了,为何 URL 中有时会出现奇怪的字符,不少时候浏览器会自动帮咱们作编码和解码的操做。就像“向日葵”的 URL 同样,中文部分由于并不在 ASCII 码中,因而浏览器进行 URL 百分号编码的形式来进行访问。

(又拍云服务名的合法范围就是在非保留字符中获取,而不能指定为任意字符)

编码的形式

最多见的编码形式就是百分号编码(pct-encoded),这也是浏览器默认的编码形式。

pct-encoded = "%" HEXDIG HEXDIG

百分号编码一个保留字符, 首先须要把该字符的 ASCII 的值表示为两个 16 进制的值, 而后在其前面放置转义字符(%)。对于非 ASCII 字符, 则须要转换为 UTF-8 字节序, 而后每一个字节按照上述方式表示。

(感兴趣的同窗能够参考百分号编码 https://zh.wikipedia.org/zh-h... 条目)
各个编程语言中也有相对应的方法能够进行百分号编码,例如 JavaScript 中就提供了多种编码方法,经常使用的有 encodeURI 和 encodeURIComponent 两个方法。

中文百分号编码的结果展现

乔巴说,在平常开发使用中,咱们使用的开发库对 URL 编码的判断标准可能并不相同,这是由于这些库所面临的网络环境中,对于特殊字符的安全处理策略各有判断,这也会致使 URL 中若是存在一些特殊字符,开发、访问过程当中可能就会出现一些奇怪的问题。在这里也建议你们使用非保留字符来设计本身程序中 URL 部分,避免一些没必要要的 BUG 产生。

听完乔巴的介绍,二狗子终于明白了为啥 URL 中出现这些奇怪的字符了。嘿嘿,这下能够和婷婷解释 URL 为何这么长咯。

推荐阅读

从 301 跳转,聊聊边缘规则的那些小妙用

企业如何高效平稳实现数据迁移

相关文章
相关标签/搜索