背景
URLSearchParmas
API 为 URL 的查询字符串(query string)提供了方便操作的接口,管理端的项目大多都应用了该接口,但这个 API 因为部分浏览器没有实现(如 IE 和旧版 Edge,详见),所以引入了相应的 polyfill(github.com/WebReflection/url-search-params )进行支持,npm 包名为 url-search-params
。
URLSearchParams
的使用方式使用详见这里。
存在问题
随着2018年4月 windows 10 系统的更新发布,Edge 浏览器的排版引擎升级到了17,开始支持 URLSearchParams
API。但是由于存在一些 bug,而且引入的 polyfill 也没有发现并进行处理,所以导致管理端的项目在 Edge 浏览器上请求时,在一定条件下会出现参数错误,最后导致请求失败。
如何复现
当请求参数中,但参数值同时出现“&”符号和“ ”空格时,URLSearchParams
的 toString()
方法就会出问题。
举个例子,下面是一个参数 q
,值为 a & b
,预期“ ”转为“+”,“&”转为"%26" :
const params = new URLSearchParams({q: 'a & b'});
params.toString();
// 期望返回“q=a+%26+b”,Edge 17浏览器则返回了“q=a+&+b”
从上面结果可以看出,Edge 17没有成功转义“&”符,由于这个字符是用于分割参数的,这样原本只有一个参数 q='a & b'
,但是由于没有成功转义”&“,就变成 q='a '
和 ' b'=''
(注意 b 前面有一个空格)两个参数了,改变了原本的请求参数。
如何解决
解决方法
Plan A
原有 polyfill 的 GitHub 代码内没有对一些实现不规范的 URLSearchParams
API 进行替换处理,解决改问题需要在模块引入前先清掉浏览器的 API( window.URLSearchParams
设为 undefined
),模块引入时就会赋予一个代码实现的 API。
原本打算在沿用旧有的 polyfill 上,不改变旧的 npm 包,应用上述方法进行修复。但是要在引用 polyfill 之前插入一段代码判断,会增加了代码耦合,所以放弃了。还有一种是直接在原有的 polyfill 代码上改,但由于该项目用 make 命令进行构建,对此不太熟悉,并且作者已将该项目转移到新的项目进行维护,构建方式也改了,最后就放弃了。
Plan B
原有 polyfill 由于已经转移到新的 Github 项目进行维护(github.com/ungap/url-search-params),构建也改为 npm 进行构建,npm 包名改为 @ungap/url-search-params
,前面加了个 scope
。
在新的 polyfill 项目代码中,作者这次有对不规范的 URLSearchParams
API 进行判断和替换,这样恰好也能在此添加 Edge 浏览器的判断。
于是就可以 fork 该项目代码修改和测试,然后给该项目提了个 pull request 给作者,很快作者就合并了代码,并发布了新的 npm 包。
然后,先把原来的 npm 包卸载,然后替换上新的 npm 包。
# 卸载
npm uninstall --save url-search-params
# 安装
npm install --save @ungap/url-search-params
最后,把模块引入的代码改下。
import URLSearchParams from 'url-search-params';
// 改为
import URLSearchParams from '@ungap/url-search-params';
最后
最近,微软官方宣布 Edge 浏览器将放弃 EdgeHTML 内核,将采用 Chromium 内核,前端开发纷纷期待新 Edge 到来。不过时间应该还长,而且用户升级也要时间,所以大家还是赶紧修复。