为何单独编 URI 组件?
JavaScript 里 encodeURI 与 encodeURIComponent 的差别,本质是「哪些字符在整链里仍要当语法符号用」。把一整条含中文的分享链接丢进只认组件级编码的网关,常见症状是「% 后面被截断」或「+ 被当成空格」。组件级编码只作用于查询值、路径段、cookie 值等「原子串」,不把主机名里的点、路径里的斜杠误编成百分号序列。和前端对表单项 name、与后端对 OAuth state 这类 JWT 片段时,先约定外层用哪种编码、内层是否 Base64url,能少一半双重编码事故。对负责联调接口、验收第三方回调的白领,用在线工具把「这一段」单独展开,比在微信里发整链截图更易被搜索引擎与文档站引用,也方便新人按图索骥。常搜「encodeURIComponent 区别」「JWT 放 query 要不要编码」「深链 跳转 丢参数」的人,要记住责任边界:谁生成明文、谁做组件级编码、谁再参与签名,只能各做一次不可逆改写,中间页若再「帮忙」编一次,用户侧就会看到莫名其妙的空白参数。把「原子串清单」附在接口评审附件里,比口头说「你懂的」更能挡住上线后的扯皮。
如何把路径段、查询值与回调 token 按组件规则编码并验收
- 先写出未编码的原始组件(如 slug、state、redirect 片段),标出哪些字符在 RFC 里属于保留字;对空格决定用「%20」还是「+」并与消费端文档一致,切勿混用两套规则。
- 仅对单个组件做编码,再按 URL 语法拼回:路径段之间仍用未编码的斜杠;若组件内本身含「/」或「?」语义,必须先整体当作值再编码,避免被路由提前切开。
- 用浏览器地址栏与 curl「--get」各测一遍,对照服务端日志里收到的逐字节;通过后在接口文档贴「编码前 / 编码后」对照表,禁止同事复制半条百分号串。
URI 组件编码常见问题
encodeURIComponent 编出来的「%」在放到 JSON 里再给前端,会不会被转义成「\u0025」导致验签失败?
JSON 序列化层可能额外转义,验签应以线上实际收到的字节流为准;联调时用抓包或服务端 raw body 对照,不要只看浏览器里美化后的 JSON。把「签名前明文字符串」写进文档并冻结版本号。
路径里有点号「.」与「..」,组件编码会不会改变目录穿越语义,Nginx 会不会仍按文件系统解析?
百分号编码不改变「..」的语义风险,安全上应在校验层规范化路径;编码只解决「非法字符」传输,不替代路径规范化。与安全同事对齐白名单目录与禁止回溯规则。
OAuth state 里塞了 JSON,先做 Base64 再做组件编码,顺序反了会怎样?
顺序反了会导致解码后不是合法 JSON 或 padding 被截断;应以授权方示例代码为准固定流水线,并在单元测试里用固定向量跑通编解码。在线工具只验证最终串,不替代你方 SDK 的约定。
Cookie 值里的分号与等号要不要按组件规则编码,和 Set-Cookie 属性里的分号如何区分?
Cookie 值本体应对保留字符编码;属性分隔仍由服务端按规范输出。不要手工拼接 Set-Cookie,使用框架 API,并在联调清单里列「非法字符样本」用例。
同一组件被 CDN 边缘函数再编一次,用户侧看到双重百分号,如何快速判断是源站还是边缘的问题?
对比源响应头与边缘响应头中的 Location 或表单 action;若边缘在已编码串上再编,应关闭自动编码或改为只编未编码子串。用在线解码分层展开,定位第一次出现非法百分号序列的位置。