`application/x-www-form-urlencoded`:互联网最老的“普通话“

`application/x-www-form-urlencoded`:互联网最老的“普通话“ 先说结论Content-Type: application/x-www-form-urlencoded的本质只有一句话把表单数据编码成一串 URL 安全的字符串塞进 HTTP Body 里发出去。它是 HTML 表单的默认提交格式也是整个 Web 最早的数据交换方式。它到底在干什么HTML 表单长这样formmethodPOSTaction/api/logininputnameusernamevaluezhangsaninputnamepasswordvalue123456/form浏览器提交时不会发 JSON而是把数据拼成这样usernamezhangsanpassword123456这就是application/x-www-form-urlencoded。名字很长拆开看关键词含义application这是一种应用层数据格式x-www-form源自 HTML 表单World Wide Web Formurlencoded每个字符都经过 URL 编码保证在 URL 里也能安全传输URL 编码是什么因为 Body 里不能直接放空格、、这些字符否则会和分隔符混淆。所以要转义原始字符编码后空格%20或%26%3D中文张%E5%BC%A0实际发出去的 Body 是usernamezhangsanpassword123456如果密码里有空格usernamezhangsanpasswordhello%20world完整请求长什么样POST /api/login HTTP/1.1 Host: example.com Content-Type: application/x-www-form-urlencoded usernamezhangsanpassword123456用 Python 的requests库importrequests requests.post(/api/login,data{username:zhangsan,password:123456})# requests 会自动设 Content-Type 并做 urlencode用urllib手动构造fromurllib.parseimporturlencode bodyurlencode({username:zhangsan,password:123456})# body usernamezhangsanpassword123456它和 JSON 的对比application/x-www-form-urlencodedapplication/json数据结构扁平键值对任意嵌套结构示例name张三age28{name:张三,age:28}能传数组吗能但要用name[]aname[]b原生支持[a, b]能传嵌套吗❌ 不行✅ 行历史1995 年就有了2000 年后才流行默认场景传统表单、OAuth现代 API哪些场景还在用它别以为它老了就没用了。这些地方你天天在用场景原因OAuth 2.0 获取 token规范明确要求用这个格式支付宝/微信支付回调传统接口设计简单登录表单够用没必要上 JSONURL query 参数本质就是 urlencoded比如 OAuth 2.0 换 token 的请求POST /oauth/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded grant_typeauthorization_codecodeabc123redirect_urihttps%3A%2F%2Fexample.com三个常见误区误区事实“它和multipart/form-data一样”完全不同。multipart用来传文件这个只能传文本键值对“GET 请求也能用这个 Content-Type”能但没意义。GET 的参数本来就在 URL 里已经是 urlencoded 了“现在都用 JSON 了这个该淘汰了”OAuth、支付回调、SSO 登录还在大量使用短期内不会消失最后application/x-www-form-urlencoded是 Web 的方言。JSON 是后来的普通话更灵活、更强大。但在 OAuth、支付、传统表单这些角落这个老格式依然是唯一指定的官方语言。不是因为它好而是因为整个生态的基础设施都建立在它上面。理解它不是为了用它而是为了在碰到它时不会一脸问号。