大侠稍等!URL 中为何出现奇怪的字符
为什么中文名称的图片打开后网址是一串乱码?为什么好好的短网址复制粘贴就变长了一大长串?罪魁祸首居然是……
杭州终于出梅了!二狗子看到气象台发布的消息,开心的不得了。杭州的雨从五月底一直下,每天除了雨还是雨,天空都是灰蒙蒙的,都快把人搞抑郁了。出梅了,天晴了,二狗子的心也随着蓝天上的白云飘荡出去了。
同事小峰峰告诉二狗子,公司后边的皇后公园,向日葵开的正好,一大片一大片的绵延出去,阳光下金灿灿的,可好看了。“要不要一起去看看?你拍点照片给婷婷呗~”
二狗子一想起女神婷婷很喜欢向日葵,拍点美丽的照片,能看到婷婷甜甜的笑,就迫不及待地拉着小峰峰往公园跑。
二狗子拍了好多照片,精挑细选了好几张,上传到自己的图片网站了。他用浏览器打开图片看了看,没有问题,非常完美,就复制了图片地址发给婷婷。
二狗子有点尴尬,明明在浏览器中是正常显示的 URL 地址,怎么复制出来就变成一堆奇怪的字符了呢?
二狗子百思不得其解,得,还是问一下自己的存储服务商——无所不能的又拍云吧。
客服乔巴接待了二狗子,并告诉了二狗子这个问题的由来。
URL - 网络资源定位符
通过互联网来访问网络中资源的时候,最常见就是通过浏览器输入资源的 URL 地址来进行访问。
URL(Uniform Resource Locator),是互联网中的一个核心概念,官方名称叫做统一资源定位符。简单的来说,URL 就是一个由网站开发者给资源在互联网上分配的地址。一般来说,每个有效的 URL 都指向单独的一个资源,这个资源可以是HTML 页面、CSS 文档,又或者是一幅图像等。
一个 URL 由不同的部分组成,其中一些是必须的,而另一些是可选的。下面我们来看下 URL 的具体组成部分:
上图就是完整的 URL 结构展示。很多时候其中的一些部分是用不到的,例如 user information。作为参考,我们可以来看一下又拍云存储的 URL 地址。
https://www.upyun.com/products/file-storage
https:// ,请求协议(scheme),指定了浏览器需要使用何种协议来与目标服务器进行通讯。常见的协议有 HTTP 和 HTTPS。
www.upyun.com,域名(host),表明请求的资源所在的服务器地址。
/products/file-storage ,资源路径地址(path),服务器通过路径来确认访问资源在服务器上的哪个位置。
一般常见的 URL 地址由这三个部分组成,其余的部分根据开发的需要,可以进行自定义。
了解 URL 的概念后,就知道二狗子的图片链接 http://fileupload-upyun.test.upcdn.net/images/向日葵1.jpg 的由来了。通过这个地址,婷婷可以访问到二狗子服务器上拍摄的向日葵图片。但是,为什么二狗子复制了浏览器地址栏中的地址,发送给婷婷的时候,URL 却变成了 http://fileupload-upyun.test.upcdn.net/images/向日葵1.jpg 了呢?
奇怪的字符 - 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/rfc3986#appendix-A)的规定,我们可以得到下面的结果。
不在 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-hans/百分号编码 条目)
各个编程语言中也有相对应的方法可以进行百分号编码,例如 JavaScript 中就提供了多种编码方法,常用的有 encodeURI 和 encodeURIComponent 两个方法。
乔巴说,在日常开发使用中,我们使用的开发库对 URL 编码的判断标准可能并不相同,这是因为这些库所面临的网络环境中,对于特殊字符的安全处理策略各有判断,这也会导致 URL 中如果存在一些特殊字符,开发、访问过程中可能就会出现一些奇怪的问题。在这里也建议大家使用非保留字符来设计自己程序中 URL 部分,避免一些不必要的 BUG 产生。
听完乔巴的介绍,二狗子终于明白了为啥 URL 中出现这些奇怪的字符了。嘿嘿,这下可以和婷婷解释 URL 为什么这么长咯。
推荐阅读
大侠稍等!URL 中为何出现奇怪的字符的更多相关文章
- 033 Url中特殊字符的处理
在url跳转页面的时候,参数值中的#不见了,一直没有处理,今天有空看了一下,后来发现后台的过滤器之类的都没有处理,就比较奇怪了,原来是特殊字符的问题. 一:Url中的特殊字符 1.说明 这里还是需要做 ...
- URL中的保留和不安全字符
书写URL时要使用US-ASCII字符集可以显示的字符. http://www.google.com 如果需要在URL中使用不属于此字符集的字符,就要使用特殊的符号对该字符进行编码. 如:最常使用的空 ...
- URL中带加号的处理
问题起因: 客户订购了一关键字为"e+h 变送器" , 在首页推荐广告中,会根据用户在search 搜索过的关键字进行一个匹配投放.技术实现是UED 通过JS 获取coo ...
- [故障引起的故事]URL中带加号的处理
问题起因: 客户订购了一关键字为"e+h 变送器" , 在首页推荐广告中,会根据用户在search 搜索过的关键字进行一个匹配投放.技术实现是UED 通过JS 获取coo ...
- url中带有加号的处理方法
最近项目中出现了一个问题,图片的路径正确,但是转成URL之后无法找到... 找了各种原因之后,最后注意到URL中的图片名称和本地路径名称有点不一样,如下图 1.URL图片 2.本地路径 上网查了一下发 ...
- Dedecms去掉URL中a目录的方法
本文实例讲述了Dedecms去掉URL中a目录的方法.分享给大家,供大家参考.具体分析如下: 使用dedecms的朋友可能会发现自己的URL目录生成是会自动带有一个/A/目录了,那么要如何去掉URL中 ...
- ${param.xxx}获取url中的参数
在项目中看到了一个很奇怪的EL表达式...${param.catid}...一直找不到param在哪里定义的...(主要是水平太屎...) 然后从网上查了一下才知道是啥... EL表达式${param ...
- url中出现井号("#")的问题
今天在asp.net mvc网站项目的前台页面里写一段js代码时,想要跳转到某个url,例如 location.href="xxxx?"+"id="+id+&q ...
- url中的jsessionid解释
(1) 这是一个保险措施 因为Session默认是需要Cookie支持的 但有些客户浏览器是关闭Cookie的 这个时候就需要在URL中指定服务器上的session标识,也就是5F4771183629 ...
随机推荐
- Ubuntu构建Docker私有仓库(Repository) 配置过程笔记
一.准备: 1.服务器(或者虚拟机2台,我的服务环境[ 阿里云服务器-Ubuntu 1804 +百度云-Ubuntu 1604]) 2.有效镜像(我这里以上一篇随笔镜像作为有效镜像https://w ...
- javascript兼容性:展开运算符 ... 的降级
展开运算符 ... 是一个很好用的ES6新特性,用的好的话,可以节约很多代码. 但是作为ES6特性,它有兼容性问题,而且Babal(在线转码网页)并不会转换展开运算符. 展开运算符大体分为两种用法:展 ...
- Spring当中循环依赖很少有人讲,今天一起来学习!
网上关于Spring循环依赖的博客太多了,有很多都分析的很深入,写的很用心,甚至还画了时序图.流程图帮助读者理解,我看了后,感觉自己是懂了,但是闭上眼睛,总觉得还没有完全理解,总觉得还有一两个坎过不去 ...
- [转载]Python ImportError: No module named 'requests'解决方法
windows解决办法1.找到easy_install.exe.一般在python的安装路径下的Scripts文件夹中,如C:\Python34\Scripts\easy_install.exe2.从 ...
- 修改 Ubuntu SSH 登录后的欢迎信息
主要就是几个文件: cd /etc/update-motd.d/ ls 00-header 90-updates-available 98-fsck-at-reboot 10-help-t ...
- centos 安装 nginx 及配置 的坑
centos 安装 nginx 教程 1.创建/etc/yum.repos.d/nginx. centos 安装 nginx 教程 1.创建/etc/yum.repos.d/nginx.repo to ...
- 配置mongoDB的错误
1,将启动配置到服务的时候没有反应,后来发现没有用管理员模式打开shell命令,所以没有反应. 2,用管理员模式的时候报错 格式问题,将由空格的路径用“”包住即可 3.启动的时候报错windows不能 ...
- windows:shellcode 代码远程APC注入和加载
https://www.cnblogs.com/theseventhson/p/13197776.html 上一章介绍了通用的shellcode加载器,这个加载器自己调用virtualAlloc分配 ...
- hadoop 莫名奇妙产生分区 0000 00001 00002
使用 multipleOutputs.write()时候,莫名奇妙的产生好多分区 job.setCombinerClass(ClassifierReduce.class); //注释掉该句 就不会 ...
- Idea Live Temlpates 自定义代码
Idea Live Temlpates 自定义代码 目的 - 加快常用代码的书写 使用## 打开Settings 快捷键Ctrl+Alt+S 选中Live Templates 选中temlpates ...