如何使用JavaScript安全地编码URL,以便将其放入GET字符串中?
var myUrl = "http://example.com/index.html?param=1&anotherParam=2";
var myOtherUrl = "http://example.com/index.html?url=" + myUrl;
我假设您需要在第二行编码myUrl变量?
如何使用JavaScript安全地编码URL,以便将其放入GET字符串中?
var myUrl = "http://example.com/index.html?param=1&anotherParam=2";
var myOtherUrl = "http://example.com/index.html?url=" + myUrl;
我假设您需要在第二行编码myUrl变量?
当前回答
不应直接使用encodeURIComponent()。
看看RFC3986:统一资源标识符(URI):通用语法
sub-delims=“!”/“$”/“&”/“'”/“(”/“)”/ "*" / "+" / "," / ";" / "="保留字符的目的是提供一组可与URI中的其他数据区分的分隔字符。
这些来自RFC3986中URI定义的保留字符不会被encodeURIComponent()转义。
MDN Web文档:encodeURIComponent()
为了更严格地遵守RFC 3986(保留!、'、(、)和*),即使这些字符没有正式的URI分隔用途,也可以安全地使用以下字符:
使用MDN Web Docs功能。。。
function fixedEncodeURIComponent(str) {
return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
return '%' + c.charCodeAt(0).toString(16);
});
}
其他回答
如前所述,要对URL进行编码,您有两个函数:
encodeURI()
and
encodeURIComponent()
两者都存在的原因是,第一种方法保留了URL,但有可能留下太多未被屏蔽的内容,而第二种方法对所有需要的内容进行编码。
使用第一个,您可以将新转义的URL复制到地址栏中(例如),这样就可以了。然而,未转义的‘&’会干扰字段分隔符,‘=’会干扰域名和值,‘+’看起来像空格。但对于简单的数据,当您希望保留要转义的内容的URL性质时,这是有效的。
第二个是您需要做的一切,以确保字符串中没有任何内容干扰URL。它保留了各种不重要的字符,使URL尽可能保持可读性而不受干扰。以这种方式编码的URL将不再作为URL工作,而不会取消其标题。
因此,如果您可以花点时间,那么在添加名称/值对之前,您总是希望使用encodeURIComponent()对名称和值进行编码,然后再将其添加到查询字符串中。
我很难找到使用encodeURI()的理由——我将把这留给更聪明的人。
encodeURIComponent()是最好的方法。
var myOtherUrl = "http://example.com/index.html?url=" + encodeURIComponent(myUrl);
但是您应该记住,与PHP版本urlencode()有一些小的不同,正如@CMS所提到的,它不会对每个字符进行编码。伙计们在http://phpjs.org/functions/urlencode/使JavaScript等效于phpencodes():
function urlencode(str) {
str = (str + '').toString();
// Tilde should be allowed unescaped in future versions of PHP (as reflected below), but if you want to reflect current
// PHP behavior, you would need to add ".replace(/~/g, '%7E');" to the following.
return encodeURIComponent(str)
.replace('!', '%21')
.replace('\'', '%27')
.replace('(', '%28')
.replace(')', '%29')
.replace('*', '%2A')
.replace('%20', '+');
}
我建议使用qs-npm包:
qs.stringify({a:"1=2", b:"Test 1"}); // gets a=1%3D2&b=Test+1
它更容易与JavaScript对象一起使用,并且为所有参数提供了正确的URL编码。
如果您使用jQuery,我会使用$.param方法。它对一个对象进行URL编码,将字段映射到值,这比对每个值调用转义方法更容易读取。
$.param({a:"1=2", b:"Test 1"}) // Gets a=1%3D2&b=Test+1
表演
今天(2020.06.12),我在浏览器Chrome 83.0、Safari 13.1和Firefox 77.0的macOS v10.13.6(High Sierra)上对所选解决方案进行了速度测试。这一结果对于大规模URL编码非常有用。
结论
encodeURI(B)似乎最快,但不建议用于URLescape(A)是一种快速的跨浏览器解决方案MDN推荐的解决方案F为中速解决方案D最慢
细节
对于解决方案A.BCDEF我进行了两次测试
对于短URL-50个字符-您可以在这里运行对于长URL-1M个字符-您可以在此处运行
函数A(url){返回转义符(url);}函数B(url){返回encodeURI(url);}函数C(url){返回encodeURIComponent(url);}函数D(url){返回新的URLSearchParams({url}).toString();}函数E(url){return encodeURIComponent(url).replace(/[!'()]/g,escape).replace(/\*/g,“%2A”);}函数F(url){return encodeURIComponent(url).replace(/[!'()*]/g,函数(c){return“%”+c.charCodeAt(0).toString(16);});}// ----------//测试// ----------var myUrl=“http://example.com/index.html?param=1&anotherParam=2";[A、B、C、D、E、F].forEach(f=>console.log(`${f.name}?url=${f(myUrl).replace(/^url=/,'')}`));此代码段仅显示所选解决方案的代码
Chrome的示例结果
不要忘记用/g标志替换所有编码的“”
var myOtherUrl = "http://example.com/index.html?url=" + encodeURIComponent(myUrl).replace(/%20/g,'+');