在JavaScript中编码URL?

nic*_*ckf 2392 javascript url encoding

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

var myUrl = "http://example.com/index.html?param=1&anotherParam=2";
var myOtherUrl = "http://example.com/index.html?url=" + myUrl;
Run Code Online (Sandbox Code Playgroud)

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

Buu*_*yen 2718

检查内置功能__CODE____CODE__.
在你的情况下,这应该工作:

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

  • @AnaelFavre因为它是为了编码整个URL,它不允许使用诸如`:`,`/`,`@`等字符.这两种方法不能互换使用,你必须知道你在编码什么使用正确的方法. (13认同)
  • 如何添加解释@cms给出的?`escape`也是一个有效的选择. (12认同)
  • 根据@CMS`creditURI`对URL编码来说并不安全. (9认同)
  • 另请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent和https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ Global_Objects /是encodeURI (6认同)
  • 注意:encodeURIComponent 仅适用于 URL 路径。查询参数遵循旧的百分比编码规范,该规范期望空格被编码为“+”而不是“%20”。请参阅[这个问题](/sf/ask/114399001/)以了解更多信息。有些服务器可能会宽容这种不正确的编码,但您的情况可能会有所不同。在现代 JavaScript 中,我建议通过 URL 或 URLSearchParams 进行编码,如[此答案](/sf/answers/4121537031/)建议的那样。 (4认同)

CMS*_*CMS 1488

你有三个选择:

  • escape() 不会编码: @*/+

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

  • encodeURIComponent() 不会编码: ~!*()'

但在你的情况下,如果你想将URL传递给GET其他页面的参数,你应该使用escapeencodeURIComponent,但不是encodeURI.

请参阅Stack Overflow问题最佳实践:escape或encodeURI/encodeURIComponent以供进一步讨论.

  • 与escape一起使用的字符编码是可变的.坚持使用encodeURI和encodeURIComponent,它们使用UTF-8. (75认同)
  • @kevzettler - 为什么要这样做?管道在URI中不具有语义重要性. (15认同)
  • 小心.该转义将非ASCII字符转换为其Unicode转义序列,如`%uxxx`. (6认同)
  • 我正在使用encodeURIComponent并注意到它不会对管道字符进行编码 (4认同)
  • @GiovanniP:允许德语,法语,日语,中文,阿拉伯语字符作为输入并通过GET或POST传递这些参数的人. (4认同)
  • 注意:从JavaScript版本1.5开始,不推荐使用escape().坚持使用encodeURI()或encodeComponent().https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape (3认同)
  • @fiatjaf非ASCII字符在域中也是完全合法的,尽管DNS系统中存储了ASCII版本.http://en.wikipedia.org/wiki/Internationalized_domain_name (2认同)

Mik*_*nan 177

坚持下去encodeURIComponent().该功能encodeURI()不打扰到编码在网址的语义重要性的字符(如"#","?"和"&").escape()不推荐使用,并且不打算编码"+"字符,这些字符将被解释为服务器上的编码空格(并且,正如其他人所指出的那样,不能对非ASCII字符进行正确的URL编码).

对于encodeURI()encodeURIComponent()其他地方之间的区别有一个很好的解释.如果您想编码的东西,以便它可以安全地被包括作为URI的组件(例如作为查询字符串参数),要使用encodeURIComponent().


Rya*_*lor 81

就个人而言,我发现很多API都想用"+"替换"",所以我使用以下内容:

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

encodeURIComponent在不同的浏览器中以不同的方式实现,escape并且不编码在URI中起作用的大多数字符(例如#和偶数/) - 它被用于完整的URI/URL而不会破坏它.

注意:您对查询字符串中使用encodeURIComponent (不是字段/值名称,绝对不是整个URL).如果你以任何其他方式执行它,它将不会编码=,?,&等字符,可能会使您的查询字符串暴露.

例:

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

  • 请注意,您应该只在第一个问号(这是URL的"查询"部分)后用+符号替换%20.假设我想浏览到`http:// somedomain /这个dir有空格/ info.php?a =这也有空格`.它应该转换为:`http://somedomain/this%20dir%20has%spaces/info.php?a =这个%20has%20also%20spaces`但许多实现允许'%20'在查询字符串中被替换为'+'.不过,你不能在URL的路径部分用'+'替换'%20',这将导致一个Not Found错误,除非你有一个带有`+`而不是空格的目录. (21认同)

Mak*_*nko 40

如果你使用的是jQuery,我会选择$.param方法.它对将对象映射到值的对象进行编码,这比在每个值上调用转义方法更容易阅读.

$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1
Run Code Online (Sandbox Code Playgroud)


m4h*_*shd 17

我认为现在到 2022 年,为了真正安全,您应该始终考虑使用URL()接口构建 URL 。它会为你完成大部分工作。所以来到你的代码,

const baseURL = 'http://example.com/index.html';

const myUrl = new URL(baseURL);
myUrl.searchParams.append('param', '1');
myUrl.searchParams.append('anotherParam', '2');

const myOtherUrl = new URL(baseURL);
myOtherUrl.searchParams.append('url', myUrl.href);

console.log(myUrl.href);
// Outputs: http://example.com/index.html?param=1&anotherParam=2
console.log(myOtherUrl.href);
// Outputs: http://example.com/index.html?url=http%3A%2F%2Fexample.com%2Findex.html%3Fparam%3D1%26anotherParam%3D2
console.log(myOtherUrl.searchParams.get('url'));
// Outputs: http://example.com/index.html?param=1&anotherParam=2
Run Code Online (Sandbox Code Playgroud)

或者...

const params = new URLSearchParams(myOtherUrl.search);

console.log(params.get('url'));
// Outputs: http://example.com/index.html?param=1&anotherParam=2
Run Code Online (Sandbox Code Playgroud)

这样的事情是保证不会失败的。


Ada*_*her 11

encodeURIComponent()是要走的路.

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

但是你应该记住,与php版本存在细微差别,urlencode()并且正如@CMS所提到的,它不会对每个字符进行编码.http://phpjs.org/functions/urlencode/的家伙使js相当于phpencode():

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', '+');
}
Run Code Online (Sandbox Code Playgroud)


Ger*_*ill 10

要编码URL,如前所述,您有两个功能:

encodeURI()
Run Code Online (Sandbox Code Playgroud)

encodeURIComponent()
Run Code Online (Sandbox Code Playgroud)

两者都存在的原因是第一个保留URL的风险是留下太多未转义的东西,而第二个则编码所需的一切.

使用第一个,您可以将新转义的URL复制到地址栏(例如),它可以工作.然而,你的未转义的'&'会干扰字段分隔符,'='会干扰字段名称和值,而'+'看起来像空格.但是对于简单的数据,当你想保留你正在逃避的URL性质时,这是有效的.

第二个是你需要做的一切,以确保你的字符串中没有任何内容干扰URL.它会保留未转义的各种不重要的字符,以便URL保持尽可能不受干扰的人类可读性.以这种方式编码的URL将不再作为URL工作而不会取消它.

因此,如果您可以花时间,您总是希望使用encodeURIComponent() - 在添加名称/值对之前,使用此函数对名称和值进行编码,然后再将其添加到查询字符串中.

我很难想出使用encodeURI()的理由 - 我会把它留给更聪明的人.


Qba*_*ack 9

现代解决方案 (2021)

由于写了其他答案,因此引入了URLSearchParams API。它可以像这样使用:

const queryParams = { param1: 'value1', param2: 'value2' }
const queryString = new URLSearchParams(queryParams).toString()
Run Code Online (Sandbox Code Playgroud)

对于您的特定示例,您可以这样使用它:

const myUrl = "http://example.com/index.html?param=1&anotherParam=2";
const myOtherUrl = "http://example.com/index.html";
myOtherUrl.search = new URLSearchParams({url: myUrl});
console.log(myOtherUrl.toString());
Run Code Online (Sandbox Code Playgroud)

这里这里也提到这个解决方案。


ser*_*erg 7

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

\n

让\xe2\x80\x99s 说我们有abc%20xyz 123输入(一个空格已经编码):

\n
encodeURI("abc%20xyz 123")            //   Wrong: "abc%2520xyz%20123"\nencodeURI(decodeURI("abc%20xyz 123")) // Correct: "abc%20xyz%20123"\n
Run Code Online (Sandbox Code Playgroud)\n


Hol*_*ger 6

您不应该encodeURIComponent()直接使用。

查看 RFC3986:统一资源标识符 (URI):通用语法

子分隔符=“!” / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" /“=”

保留字符的目的是提供一组可与 URI 中的其他数据区分开的分隔字符。

RFC3986 中 URI 定义中的这些保留字符不会被 转义encodeURIComponent()

MDN 网络文档:encodeURIComponent()

为了更严格地遵守 RFC 3986(保留 !、'、(、) 和 *),即使这些字符没有正式的 URI 分隔用途,也可以安全地使用以下字符:

使用 MDN Web 文档功能...

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


Nar*_*chu 5

我用普通的javascript试过类似的东西

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


Wil*_*een 5

什么是网址编码:

当 URL 中有特殊字符时,应该对 URL 进行编码。例如:

console.log(encodeURIComponent('?notEncoded=&+'));
Run Code Online (Sandbox Code Playgroud)

我们可以在这个例子中观察到,除了字符串之外的所有字符notEncoded都用 % 符号编码。URL 编码也称为百分比编码,因为它使用 % 转义所有特殊字符。然后在这个 % 符号之后,每个特殊字符都有一个唯一的代码

为什么需要 URL 编码:

某些字符在 URL 字符串中具有特殊值。例如,? 字符表示查询字符串的开始。为了在网络上成功定位资源,必须区分字符是作为字符串的一部分还是作为 url 结构的一部分。

我们如何在JS中实现URL编码:

JS 提供了一堆内置的实用程序函数,我们可以使用它们来轻松地对 URL 进行编码。这是两个方便的选项:

  1. encodeURIComponent(): 将 URI 的一个组件作为参数并返回编码的 URI 字符串。
  2. encodeURI(): 将 URI 作为参数并返回编码的 URI 字符串。

示例和注意事项:

请注意不要将整个 URL(包括方案,例如 https://)传入encodeURIComponent(). 这实际上可以将其转换为不起作用的 URL。例如:

// for a whole URI don't use encodeURIComponent it will transform
// the / characters and the URL won't fucntion properly
console.log(encodeURIComponent("http://www.random.com/specials&char.html"));

// instead use encodeURI for whole URL's
console.log(encodeURI("http://www.random.com/specials&char.html"));
Run Code Online (Sandbox Code Playgroud)

我们可以观察到,如果我们将整个 URL 放入其中encodeURIComponent,正斜杠 (/) 也被转换为特殊字符。这将导致 URL 不再正常运行。

因此(顾名思义)使用:

  1. encodeURIComponent 在要编码的 URL 的某个部分。
  2. encodeURI 在要编码的整个 URL 上。


Kam*_*ski 5

表现

今天(2020.06.12)我在macOS v10.13.6 (High Sierra) 上使用 Chrome 83.0、Safari 13.1 和 Firefox 77.0 浏览器对所选解决方案进行了速度测试。此结果对于大规模 URL 编码非常有用。

结论

  • encodeURI(B) 似乎最快,但不推荐用于 URL
  • escape(A) 是一个快速的跨浏览器解决方案
  • MDN推荐的解决方案 F中等速度
  • 解决方案D是最慢的

在此输入图像描述

细节

对于解决方案 A B C D E F 我执行两个测试

function A(url) {
    return escape(url);
}

function B(url) {
    return encodeURI(url);
}

function C(url) {
    return encodeURIComponent(url);
}

function D(url) {
    return new URLSearchParams({url}).toString();
}

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

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



// ----------
// TEST
// ----------

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=/,'')}`));
Run Code Online (Sandbox Code Playgroud)
This snippet only presents code of chosen solutions
Run Code Online (Sandbox Code Playgroud)

Chrome 的示例结果

在此输入图像描述