HTTP 冷知识 | HTTP 请求中,空格应该被编码为 %20 还是 + ?
HTTP 请求中,空格应该被编码为什么?今天我们走进 RFC 文档和 W3C 文档,了解一下这个「史诗级」大坑。
1.%20
还是 +
?
开始讲解前先看个小测试,在浏览器里输入 blank test
( blank
和 test
间有个空格),我们看看浏览器如何处理的:
从动图可以看出浏览器把空格解析为一个加号「+」。
是不是感觉有些奇怪?我们再做个测试,用浏览器提供的几个函数试一下:
encodeURIComponent("blank test") // "blank%20test"
encodeURI("q=blank test") // "q=blank%20test"
new URLSearchParams("q=blank test").toString() // "q=blank+test"
代码是不会说谎的,其实上面的结果都是正确的,encode 结果不一样,是因为 URI 规范和 W3C 规范冲突了,才会搞出这种让人疑惑的乌龙事件。
2.冲突的协议
我们首先看看 URI 中的保留字,这些保留字不参与编码。保留字符一共有两大类:
gen-delims: :
/
?
#
[
]
@
sub-delims: !
$
&
'
(
)
*
+
,
;
=
URI 的编码规则也很简单,先把非限定范围的字符转为 16 进制,然后前面加百分号。
空格这种不安全字符转为十六进制就是 0x20,前面再加上百分号 %
就是 %20
:
所以这时候再看 encodeURIComponent
和 encodeURI
的编码结果,就是完全正确的。
既然空格转为%20
是正确的,那转为 +
是怎么回事?这时候我们就要了解一下 HTML form 表单的历史。
早期的网页没有 AJAX 的时候,提交数据都是通过 HTML 的 form 表单。form 表单的提交方法可以用 GET 也可以用 POST,大家可以在 MDN form 词条上测试:
经过测试我们可以看出表单提交的内容中,空格都是转为加号的,这种编码类型就是 application/x-www-form-urlencoded
,在 WHATWG 规范里是这样定义的:
到这里基本上就破案了,URLSearchParams
做 encode 的时候,就按这个规范来的。我找到了 URLSearchParams
的 Polyfill 代码,里面就做了 %20
到 +
的映射:
replace = {
'!': '%21',
"'": '%27',
'(': '%28',
')': '%29',
'~': '%7E',
'%20': '+', // <= 就是这个
'%00': '\x00'
}
规范里对这个编码类型还有解释说明:
The
application/x-www-form-urlencoded
format is in many ways an aberrant monstrosity, the result of many years of implementation accidents and compromises leading to a set of requirements necessary for interoperability, but in no way representing good design practices. In particular, readers are cautioned to pay close attention to the twisted details involving repeated (and in some cases nested) conversions between character encodings and byte sequences. Unfortunately the format is in widespread use due to the prevalence of HTML forms.这种编码方式就不是个好的设计,不幸的是随着 HTML form 表单的普及,这种格式已经推广开了
其实上面一大段句话就是一个意思:这玩意儿设计的就是 ,但积重难返,大家还是忍一下吧
3.一句话总结
URI 规范里,空格 encode 为
%20
,application/x-www-form-urlencoded
格式里,空格 encode 为+
实际业务开发时,最好使用业内成熟的 HTTP 请求库封装请求,这些杂活儿累活儿框架都干了;
如果非要使用原生 AJAX 提交
application/x-www-form-urlencoded
格式的数据,不要手动拼接参数,要用URLSearchParams
处理数据,这样可以避免各种恶心的编码冲突。
4.文章推荐
本文选自我的长文HTTP 规范中的那些暗坑,想要了解更多可点击原文查看。
更多推荐:
webpack 中最易混淆的 5 个知识点,掘金快 800 赞了 webpack dll 是个什么东西,看完就能摆脱繁琐的 dll 配置 React Native 性能优化指南从渲染层的角度分析了 RN 性能优化的 6 个点,并以图文形式讲解了 FlatList 的实现原理 Web Scraper——轻量数据爬取利器 介绍了一个小巧的浏览器爬虫插件,可以实现简单的数据爬取功能
最后推荐一下我的个人公众号:「卤蛋实验室」,平时会分享一些前端技术和数据分析的内容,大家感兴趣的话可以关注一波:
HTTP 冷知识 | HTTP 请求中,空格应该被编码为 %20 还是 + ?的更多相关文章
- (转)HTTP请求中URL地址的编码和解码
HTTP请求中,类似 http%3A%2F%2Fwww.baidu.com%2Fcache%2Fuser%2Fhtml%2Fv3Jump.html 的地址 如何解码成 http://www ...
- 有趣的冷知识:编程中Foo, Bar 到底什么意思?
转自:编程中Foo, Bar 到底什么意思? 1 前言 在很多国外计算机书本和一些第三份开源软件的Demo中经常用到两个英文单词Foo,Bar.这到底是什么意思呢?从步入屌丝界的IT生活见到这两个单词 ...
- python冷知识(续)
python 冷知识 1.交互式中修改最大递归深度 大家都知道使用递归是有风险的,递归深度过深容易导致堆栈的溢出. 那到底,默认递归次数限制是多少呢? 可以使用sys这个库来查看 >>&g ...
- URL中的空格字符如何编码
URL encoding the space character: + or %20? 简单理解: ‘?’前的路径中的空格必须为’20%’ ‘?’后的参数中空格可以被编码成’+’(正常情况),然而有时 ...
- 【原创】http请求中加号被替换为空格?源码背后的秘密
这是why技术的第**20**篇原创文章
上一篇文章分享了 Python中的那些冷知识,地址在这里 盘点 Python 中的那些冷知识(一) 今天将接着分享!! 06. 默认参数最好不为可变对象 函数的参数分三种 可变参数 默认参数 关键字参 ...
- requests(二): json请求中固定键名顺序&消除键和值之间的空格
继上一篇requests发送json请求的文章后,实际工作中遇到了以下2种情况. 1:服务端要求json字符串,键名的顺序固定 2.服务端对于接收到的json数据中,若key和value之间有空格, ...
- Python 浮点数的冷知识
本周的PyCoder's Weekly 上分享了一篇小文章,它里面提到的冷知识很有意思,我稍作补充,分享给大家. 它提到的部分问题,读者们可以先思考下: 若两个元组相等,即 a==b 且 a is b ...
- Http请求中的Content-Type
转载至:https://segmentfault.com/a/1190000013056786?utm_source=tag-newest 一 前言 ----现在搞前端的不学好http有关的知识已经不 ...
随机推荐
- jQuery的事件绑定与触发 - 学习笔记
jQuery的事件绑定与触发 事件绑定 自动触发事件 常用的鼠标事件 事件冒泡和默认行为 事件冒泡 默认行为 获得当前鼠标的位置和按键 jQuery的事件绑定与触发 事件绑定 基本绑定 $(eleme ...
- MATLAB矩阵的表示
矩阵是matlab中最基本的数据对象. l 矩阵的建立 l 冒号表达式 l 结构矩阵和单元矩阵 1.矩阵的建立 (1)利用直接输入法建立矩阵:将矩阵的元素用中括号括起来,按矩阵行的顺序输入各元素 ...
- python 读hdf4文件,再转写成一个tif文件
1.安装pyhdf包 (1)通过此链接查找并下载pyhdf包:https://www.lfd.uci.edu/~gohlke/pythonlibs/#pygame(根据自己的系统及python版本选择 ...
- spark on yarn安装
网上关于spark的安装说明很多了,这里就以spark pre-build with user provided hadoop 安装包为例讲解, 下载spark pre-build with us ...
- 图形学_opengl纹理映射
学了半学期的图形学,除了几个用python或是matlab比较方便的实验外,用的大多数是opengl,在这总结一下纹理贴图实验中opengl的用法. 1.编译器连接静态库 有用到glaux.h的程序, ...
- python统计英文文本中的回文单词数
1. 要求: 给定一篇纯英文的文本,统计其中回文单词的比列,并输出其中的回文单词,文本数据如下: This is Everyday Grammar. I am Madam Lucija And I a ...
- 实战!我用 Wireshark 让你“看得见“ TCP
每日一句英语学习,每天进步一点点: 前言 为了让大家更容易「看得见」 TCP,我搭建不少测试环境,并且数据包抓很多次,花费了不少时间,才抓到比较容易分析的数据包. 接下来丢包.乱序.超时重传.快速重传 ...
- 机器学习必会工具gensim
import jieba import gensim from gensim import corpora from gensim import models from gensim import s ...
- java web基础
WEB基础 C/S:即服务器-客服机(Client-Server)结构.C/S结构通常采用两层结构,服务器负责数据的管理,客户机负责完成与用户的交互任务.客户通过局域网与服务器相连,接受用户的请求,并 ...
- jdk1.8的一些特性
一.jdk1.8的特性: Lambda表达式 函数式接口 方法引用 接口的默认方法和静态方法 Optional Streams 并行数组 新时间日期API 二.Lambda表达式: Lambda 表达 ...