如何使用JavaScript安全地编码URL,以便将其放入GET字符串中?

var myUrl = "http://example.com/index.html?param=1&anotherParam=2";
var myOtherUrl = "http://example.com/index.html?url=" + myUrl;

我假设您需要在第二行编码myUrl变量?


当前回答

使用fixedEncodeURIComponent函数严格遵守RFC 3986:

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}

其他回答

我建议使用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的示例结果

let name=`bbb`;params=“name=${name}”;var myOtherUrl=`http://example.com/index.html?url=${encodeURIComponent(params)}`;console.log(myOtherUrl);

现在在ES6中使用backtick来编码URL

试试这个-https://bbbootstrap.com/code/encode-url-javascript-26885283

我用普通JavaScript做了类似的尝试:

function fixedEncodeURIComponent(str){
    return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
}

为了防止双重编码,最好在编码之前解码URL(例如,如果您处理的是用户输入的URL,可能已经编码)。

假设我们有abc%20xyz 123作为输入(一个空格已编码):

encodeURI("abc%20xyz 123")            //   Wrong: "abc%2520xyz%20123"
encodeURI(decodeURI("abc%20xyz 123")) // Correct: "abc%20xyz%20123"