URL(URI) 中的编码与乱码(下)--查询字符串(query string)中的编码

news2024/11/24 22:29:49

在上篇中, 初步谈论了 URL 中含有中文字符时的转义编码, 提到了所使用的编码是 utf-8.

不过你可能会有点疑问, 一定都是要用 utf-8 编码吗? 还是因为页面编码本身是 utf-8 的缘故呢? 毕竟在那个例子中, 页面的编码也恰好是 utf-8.

在 GBK 编码页面下的 URL 转义

这次, 将继续测试页面编码是 gbk 时的情况, 如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="GBK">
<title>带中文的 URL(GBK)</title>
</head>
<body>
	测试带中文的 URL,页面编码为:GBK
	<br> 中文链接:
	<a href="你好/index.html">你好/index.html</a>
	<br> 中文链接并带有中文查询字符串:
	<a href="你好/index.html?s=你好">你好/index.html?s=你好</a>
</body>
</html>

打开时, 是正常的:

gbk 编码页面 中文 url 浏览器测试

当然, 你可能会想, 打开前, 还不知道页面的编码呢, 那么事实上也是如此, 此时请求的 url 依然是 utf-8 编码的:

gbk 编码页面 中文 url request header

那么继续点击其中的"你好/index.html"链接时呢? 结果页面还是 OK 的:

中文路径 url 从 gbk 页面发出 浏览器测试

查看其发出的 url:

中文路径 url 从 gbk 页面发出 request header

尽管此时在 gbk 编码的页面发出此请求, 但它的编码还是 utf-8.

那么是否就可以得出结论, 即 url 中的编码始终是用 utf-8 呢? 然而事情没有那么简单, 正像你看到页面中还有一个链接, 下面那个带有中文 查询字符串 的链接:

你好/index.html?s=你好

在 gbk 页面下点击它时是怎样的情况呢? 在此之前, 先要对 URL 中的结构做些了解.

URL 中的结构简介

多数的 URI 结构可以这样去划分:

<scheme>://:@<host>:<port>/<path>;?<query>#<frag>

下面从一些例子中具体介绍各个部分的含义. 一个具体例子:

https😕/xiaogd.net:443/?p=1699

其中:

  • scheme(协议, 方案)为 https;
  • host(主机名, 域名)为 xiaogd.net,
  • 端口(port)为 443;
  • query(查询字符串)为 p=1699.

这是上一篇文章的一个短连接(short link), 点击它会重定向到上一篇章中(已失效).

注: 这个例子中, 没有用户名, 密码, 没有路径(path)(也可以认为有一个路径, 就是根路径"/"本身), 没有 params, 也没有 frag. https 协议的默认端口即为 443, 通常可以省略.

其中查询字符串 query strings, uri 规范中的标准叫法为 query component(查询组件), 用分隔符问号 “?” 与其它部分隔开, 具体内容可以由多个 键值对 组成, 中间由 “&” 符号分隔, 键与值之间用分隔符等号 “=” 隔开:

如: http://localhost/foo?userid=9527&gender=male 中的查询字符串有两个键值对:

  1. userid=9527
  2. gender=male

另一个例子:

http😕/exp.xiaogd.net:80/demo/css/stroke-animate/stroke-animation.html

其中, 路径 path 为 /demo/css/stroke-animate/stroke-animation.html.

注: http 协议的默认端口即为 80, 通常可以省略;如果不是 80 就不能省略, 如测试常用的 8080 端口, 就要显式地在 url 中带上, 这一端口来自于 web server 启动时所绑定(监听)的那个.

frag(fragments, 片段, 分段) 是页面内的链接(锚点), 位于最后, 用井号(#)跟其它部分隔开, 严格地讲它不属于 url 的一部分, 它的值通常即为页面内某个标题元素的 id. 一个具体例子:

https://www.xiaogd.net/md/url-charset-encoding-and-mojibake-1#tomcat_与_URIEncoding_设置

点击它与点击 https://www.xiaogd.net/md/url-charset-encoding-and-mojibake-1/ 都是跳到同一个页面, 但它会滚动到页面内的某个元素下(通常为某个子标题), 跟你打开这个页面单击那个目录下的标题类似:

url fragments 页内链接 示例

其实上图目录下的就是这种页面内的锚点(frag), 分享一个比较长的页面时, 这种方式能够更加精准地定位到页内的某个段落上, 免得别人去翻找.

你可以亲自点击上述两个链接看看结果有什么不同!

其它的一些例子如:

  • ftp://anonymous@ftp.prep.ai.mit.edu/pub/gnu
  • ftp://anonymous:my_passwd@ftp.prep.ai.mit.edu/pub/gnu
  • http://joe:joespasswd@www.joes-hardware.com/sales_info.txt
  • ftp://prep.ai.mit.edu/pub/gnu;type=d
  • http://www.joes-hardware.com/hammers;sale=false/index.html;graphics=true

包含有其它一些协议, 如 ftp;还有用户名, 密码的例子, 以及 param 的例子.

这些例子来自 <<Http 权威指南>> 一书中.

param 跟查询字符串 query 很类似, 跟在 path 后面, 用分号";"与 path 隔开, 但这种用法很罕见, 反正我是没怎么见过用 param 的, 一般都是用 query.

URL 查询字符串(query component)中的编码

这里主要关注 query, 在明白它是怎么回事后, 在 gbk 页面下点击带有中文查询字符串的链接时:

url 中文查询字符串链接 页面

结果是这样的:

URL 中文查询字符串 地址栏显示

会发现情况有不同了, 地址栏中路径上的"你好"两字还能正确显示为中文, 但后面的查询字符串中的"你好", 同样的字符此刻却显示为一串转义字符 “%C4%E3%BA%C3”.

从四字节的编码 “C4 E3 BA C3” 来看, 显然是 gbk 编码, 而不是 utf-8 编码, 因为对于 utf-8 而言, 常见汉字一个字符至少也是三字节的编码, 而现在是一个字符两字节, 所以显然是 gbk 编码.

此刻去看请求头中的 url:

URL 中文查询字符串 request header

虽然同样是 “你好” 两字符, 编码却出现了不同. 在路径中是 utf-8 编码, 在查询字符串中却是页面的编码, gbk.

而当在页面的编码是 utf-8 的页面中点击同样的链接字符串作跳转时, 编码则是一致的:

URL 中文查询字符串 地址栏显示和 request header utf-8 编码

可以看到地址栏此刻都显示为"你好", 而请求头中的真实 url 两处的编码也确实是相同的.

综上, 可以得出这样一个结论: URL 路径中的转义使用 utf-8 编码, 但查询字符串中的转义却是跟随页面编码的.

在其它浏览器中的测试

在火狐浏览器(firefox)中的测试也能得出类似结论, 这里不再列举.

在微软的 Edge 和 IE(11)中测试则有些要注意的, 即使是在 gbk 页面下点击, 地址栏的显示始终是一致的:

edge 浏览器 中文url 路径及地址栏 显示

这个地址栏的值拷贝出来它也是字符形式, 而不是转义的形式, 这跟 chrome 等浏览器的行为又不一样. 当用开发人员工具查看请求头时:

edge 浏览器 中文url request header

显示是混乱的, 从某些字符来看, 像是使用了同一种编码, 但有的有转义, 有的又没有. 这个地方应该是它的调试工具本身的 bug.

如果在外面用 Fiddler 抓包工具查看, 发现它其实还是跟 chrome, firefox 一样的, 路径用 utf-8, 查询字符串跟随页面编码:

fiddler edge 浏览器 中文url request header

IE 11 跟 Edge 的行为类似, 而模拟一些更早的 IE 版本时, 比如 IE 9, 情况又有所不同:

fiddler ie11 浏览器 中文url request header

路径处还是 utf-8 的转义形式, 但是查询字符串中显示一些乱码的字符, 查看其十六进制形式时:

fiddler ie11 浏览器 中文url request header hexview

发现编码确实为 gbk, 但它没有转义. 当页面编码为 utf-8 时, 查询字符串的编码也是 utf-8, 但同样的, IE 9 不会自动帮我们把查询字符串转义.

更多的浏览器及版本下的行为, 这里也无法一一去测试, 读者如果碰到问题, 可自行具体分析.

URL 编码使用的总结与建议

所以, 总结来说:

  1. url 路径中的中文, 浏览器会自动进行 utf-8 编码转义;
  2. 查询字符串中, 现代浏览器会使用页面编码来转义;
  3. 查询字符串中, 较早期的浏览器也会用页面编码, 但不会为你转义, 你要自己做转义.

另外, 前面提到, server 端也要作相应处理, 比如 tomcat 中你可能要配置 URIEncoding, 而如果你的 url 中如果有多种编码方式共存, 处理起来会非常棘手, 甚至是不可能的.

如果页面要用 gbk 编码, 那么 url 路径中就不要带有中文了, 这时就查询字符串中有转义的 gbk 编码, 可以避免出现两种编码, 这时可在 URIEncoding 中设置为 gbk 来正确接收 url .

如有可能, 最好在所有环节使用 utf-8 编码, 在需要转义的地方, 手动地进行转义, 如此放可保证在各种情况下不会出现问题.

关于 URL 中的编码与乱码的介绍就到这里, 这里虽然也涉及到了用查询字符串向后端服务器传递参数, 但暂时还没有在服务器端尝试接收这些参数, 参数接收的话题将在后续的表单(form)提交时的编码与乱码中一起讨论.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/708239.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux10.地址空间

1.几乎所有的语言&#xff0c;如果它有地址的概念&#xff0c;这个地址一定不是物理地址&#xff0c;是虚拟地址(线性地址)。 2.诸如网卡&#xff0c;硬盘和显卡等外设内部也具有寄存器。 3.在makefile中&#xff0c;gcc -o 文件A 文件1 文件2(…)可以写成 :gcc -o $ $^ 4.地…

程序员常用的几个效率小工具,可好用了!

目录 &#x1f5a5;️ Hexed.it &#x1f5bc;️ Carbon &#x1f5bc;️ Draw.net 今天给大家推荐几个平时工作学习中常用到的小工具&#xff0c;让你效率拉满&#xff01; &#x1f5a5;️ Hexed.it 在线地址&#xff1a;HexEd.it - Browser-based Online and Offline He…

增强深度学习与对抗训练对癫痫发作的鲁棒预测

标题&#xff1a;Augmenting Deep Learning with Adversarial Training for Robust Prediction of Epilepsy Seizures Abstract: 癫痫是一种慢性疾病&#xff0c;涉及异常的大脑活动&#xff0c;导致患者失去对意识或运动活动的控制。因此&#xff0c;在癫痫发作之前检测出癫…

Learn Mongodb DB数据库部署 ②

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; PHP MYSQL &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &#x1f44…

类加载的时机

类加载的时机 类的生命周期 类从被加载到虚拟机内存开始&#xff0c;到卸载出内存为止&#xff0c;它的整个生命周期包括以下 7 个阶段&#xff1a; 加载 验证 准备 解析 初始化 使用 卸载 验证、准备、解析 3 个阶段统称为连接。 加载、验证、准备、初始化和卸载这 5 个阶段的…

【MATLAB第49期】基于MATLAB的深度学习ResNet-18网络不平衡图像数据分类识别模型

【MATLAB第49期】基于MATLAB的深度学习ResNet-18网络不平衡图像数据分类识别模型 一、基本介绍 这篇文章展示了如何使用不平衡训练数据集对图像进行分类&#xff0c;其中每个类的图像数量在类之间不同。两种最流行的解决方案是down-sampling降采样和over-sampling过采样。 在…

力扣 -- 64.最小路径和

题目链接&#xff1a;64. 最小路径和 - 力扣&#xff08;LeetCode&#xff09; 下面是用动态规划的思想解决这道题的过程&#xff0c;相信各位小伙伴都能看懂并且掌握这道经典的动规题目的。 参考代码&#xff1a; class Solution { public:int minPathSum(vector<vector…

filezilla 刷新文件

ubuntu上的filezilla一直右键找不到文件刷新的选项&#xff0c;今天终于找到了 点击那个循环利用的按钮&#xff0c;就是刷新文件和文件夹&#xff0c;这个和mac上的操作有点不一致&#xff0c;很奇怪哈

PHP --- 基础(01)

简单介绍 &#xff08;1&#xff09;PHP基本语法操作 <?php $iphone13 5880; // 变量首字母不能是数字&#xff0c;同时变量区分大小写 $iphone12 5000; // 变量名尽量有意义 $shen $iphone13 $iphone12 echo $shen; // echo是在php中常用的输出、显示功能的命令 ?&…

使用 arpl 在 PVE 上安装黑群晖

arpl 是 GitHub 上开源的自动装载程序&#xff0c;能够实现使用 arpl 在物理机或虚拟机中安装黑群晖 1. 下载 arpl 在 GitHub 项目 fbelavenuto/arpl 的 Releases 中选择下载最新版本&#xff0c;选择 img.zip 后缀的文件进行下载 解压后可以得到一个名为 arpl.img 的文件&am…

一.《泽诺尼亚》背包物品数据分析和遍历

寻找突破口 1.首先寻找突破口,围绕一个“变”字去找 2.之前在别的课程中也给同学们说过,我们在找背包物品遍历,无非就是要先拿到物品对象 3.然而要拿到物品对象,必须先拿到物品属性,然后逆向分析拿到物品对象 4.那么问题来了, 怎么拿到物品属性呢&#xff1f; 5.这时候就要…

Fiddler如何进行弱网测试

目录 前言 1、Fiddler设置 2、手机设置 3.设置模拟调制解调器的速度&#xff1a; 4.设置手机代理 前言 使用Fiddler对手机App应用进行抓包&#xff0c;可以对App接口进行测试&#xff0c;也可以了解App传输中流量使用及请求响应情况&#xff0c;从而测试数据传输过程中流量…

上海师范大学Windows端VPN使用教程及课表查询方法

1、首先强调&#xff1a;学生电子邮件和 VPN 服务须在修改初始密码之后才能登录使用。 2、其次&#xff1a; 学校已为每位新生开通了统一身份认证账号&#xff08; CUID &#xff09;&#xff08;如&#xff1a;1000101010, 详见录取 通知书上的 CUID&#xff09; 。 初始密码…

protobuf的Proto3语法学习 (二)

文章目录 五、proto3语法详解1. 字段规则2. 消息类型的定义与使⽤2.1 定义2.2 使⽤2.3 创建通讯录2.0版本2.3.1 通讯录2.0的写⼊实现2.3.2 通讯录2.0的读取实现2.3.3 验证写入是否正确 3. enum类型3.1 定义规则3.2 定义enum类型的注意事项3.3 升级通讯录⾄2.1版本 4. Any类型4.…

【SpringBoot】基于SSM框架的题库系统的设计与实现

文章结构 课题&#xff1a;一、项目简介主要功能技术选型 二、 模块介绍学生端教师端(一)考试管理(二)试题管理(三)学生成绩管理 管理员三、 B站项目演示地址 四、本项目其余相关博客 课题&#xff1a; 题库系统的设计与实现一、项目简介 简介&#xff1a;主要分为三个端&…

总结下 89C52 单片机中 Timer 2 作为定时器(工作在16位自动重装方式)的使用方法

从应用角度来学习&#xff0c;一切从效率&#xff08;益&#xff09;出发。 计数功能是指使用计数器的计数脉冲输入端&#xff08;T0对应P3.4&#xff0c;T1对应P3.5&#xff0c;T2对应P1.0&#xff09;对外部脉冲信号的计数&#xff1b;定时功能是指对内部晶振驱动时钟进行计…

Unittest初体验

前言 Unittest优点 UnitTest是Python自带的一个单元测试框架&#xff0c;具有以下特点&#xff1a; 1)轻量、简易&#xff0c;易于上手 2)根据自己的要求&#xff0c;定制优化&#xff0c;如httprunner就是基于unittest完成的 3)能够组织多个用例去执行 4)提供丰富的断言…

熔断与降级 Hystrix

一、Hystrix(豪猪)简介 1、Hystrix的设计目的 &#xff08;1&#xff09;对依赖服务调用时出现的调用延迟和调用失败进行控制和容错保护。 &#xff08;2&#xff09;阻止某一个依赖服务的故障在整个系统中蔓延&#xff0c;服务A->服务B->服务C&#xff0c;服务C故障了…

结构体和数据结构--结构体数组的定义和初始化

目录 一、结构体数组的定义 二、结构体数组的初始化 一、结构体数组的定义 一个结构体变量只能表示学生成绩管理表中的一个学生的记录信息&#xff0c;代表其中的一个实例&#xff0c;而实际数据库中有多个学生的记录&#xff0c;每个记录对应一个学生的信息&#xff0c;如何…

通过Python的tkinter,在滚动条中添加各种控件

在用tkinter设计UI时,需要在有限的空间里面堆叠多行元素,此时就需要用到滚动条的效果。案例效果如图: 框架思路: 通过tkinter中的画布canvas与滚动条scrollbar进行联动,并将所有的控件都塞入到画布canvas中。其中有一步对画布大小的设置也很关键,即canvas.config(width=…