共计 1399 个字符,预计需要花费 4 分钟才能阅读完成。
问题场景
上周排查一个生产环境 bug 时,发现用户搜索包含 # 的内容时服务端返回 500 错误。经过定位发现是前端直接拼接 URL 时未编码特殊字符,导致 # 后的参数被浏览器识别为锚点而丢失。这种低级错误本可以通过简单的编码避免,却导致关键功能不可用。下面我们系统梳理 GET 请求参数传递的正确姿势。

参数构造方案
1. 原生字符串拼接(不推荐)
// 问题代码:未处理特殊字符
const keyword = 'C# 编程';
const url = `/search?q=${keyword}`; // 实际发送的是 /search?q=C
// 正确写法
const safeUrl = `/search?q=${encodeURIComponent(keyword)}`; // 输出 /search?q=C%23 编程
2. URLSearchParams(现代浏览器推荐)
const params = new URLSearchParams();
params.append('page', 1);
params.append('filter', 'price>100');
// 自动处理数组参数
params.append('category', ['前端', '后端']); // 转换为 category= 前端 &category= 后端
fetch(`/api/products?${params}`);
3. 复杂对象处理
当需要传递嵌套对象时,通常需要序列化:
const filters = {price: { min: 100, max: 500},
tags: ['促销', '新品']
};
// 方案 1:JSON 序列化(需服务端配合解析)const params = new URLSearchParams();
params.append('filters', JSON.stringify(filters));
// 方案 2:扁平化处理(推荐 RESTful 风格)// 生成 ?price_min=100&price_max=500&tags= 促销 &tags= 新品
安全实践
URL 长度限制
不同浏览器对 URL 长度限制不同(Chrome~2MB),超长参数建议:
- 改用 POST 请求
- 压缩参数(如 base64 编码)
- 拆分多次请求
敏感参数防护
- 永远不要用 GET 传递密码或 token
- 敏感 ID 参数应进行混淆处理
- 启用 HTTPS 防止中间人窃听
CSRF 防护示例
// axios 拦截器自动添加 token
axios.interceptors.request.use(config => {if (['get', 'GET'].includes(config.method)) {
config.params = {
...config.params,
_token: getCSRFToken()};
}
return config;
});
生产环境检查清单
发送 GET 请求前务必确认:
- 所有动态参数都经过
encodeURIComponent处理 - 数组参数使用
param[]=1¶m[]=2格式 - 敏感参数不在 URL 中暴露
- 考虑浏览器 URL 长度限制
- 接口有 CSRF 防护机制
思考题
- 当参数超过 URL 限制时,如何优雅地从 GET 切换到 POST?
-
方案:保持接口路由不变,通过请求头
X-Method-Override: POST声明 -
如何设计参数校验中间件?
- 建议:采用 JSON Schema 规范,在拦截器中统一验证参数类型和范围
经过这些实践,我们的搜索功能再没出现过参数丢失问题。GET 请求看似简单,但魔鬼藏在细节里。
正文完
