如何使用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(而不是其他)。

然而,我发现许多API都想用“+”替换“”,所以我不得不使用以下方法:

const value = encodeURIComponent(value).replace('%20','+');
const url = 'http://example.com?lang=en&key=' + value

escape在不同浏览器中的实现方式不同,encodeURI不编码许多字符(如#和甚至/)——它可以在完整的URI/URL上使用,而不会破坏它——这并不是非常有用或安全的。

正如@Jochem在下面指出的,您可能希望在(每个)文件夹名称上使用encodeURIComponent(),但无论出于什么原因,这些API似乎不希望在文件夹名称中使用+,所以普通的encodeURIComponents非常有用。

例子:

const escapedValue = encodeURIComponent(value).replace('%20','+');
const escapedFolder = encodeURIComponent('My Folder'); // no replace
const url = `http://example.com/${escapedFolder}/?myKey=${escapedValue}`;

其他回答

查看内置函数encodeURIComponent(str)和encodeURI(str)。在您的情况下,这应该有效:

var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);

我建议使用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

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

您有三个选项:

escape()不会编码:@*/+encodeURI()不会编码:~@#$&*()=:/,;?+'encodeURIComponent()不会编码:~*()'

但在您的情况下,如果要将URL传递到其他页面的GET参数中,则应该使用escape或encodeURIComponent,而不是encodeURI。

有关详细讨论,请参阅堆栈溢出问题最佳实践:转义或encodeURI/encodeURIComponent。

表演

今天(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的示例结果