Кодировать URL в JavaScript?

2470

Как безопасно кодировать URL-адрес с помощью JavaScript, чтобы его можно было вставить в строку GET?

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

Я предполагаю, что вам нужно закодировать myUrlпеременную во второй строке?

nickf
источник
22
Попробуйте заглянуть в encodeURI () и decodeURI () .
Зак Человек
Смотрите функцию JavaScript urlencode .
Янни
1
Вы можете использовать этот инструмент здесь: phillihp.com/toolz/url-encode-decode
phillihp
2
encodeURIComponent ()
Эндрю

Ответы:

2791

Проверьте встроенную функцию encodeURIComponent (str) и encodeURI (str) .
В вашем случае это должно работать:

var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);
Буу Нгуен
источник
12
Как насчет добавления объяснения, которое дал @cms? escapeтакже является допустимым вариантом.
hitautodestruct
11
в соответствии с @CMS encodeURIне совсем безопасен для кодирования URL.
Ifnot
13
@AnaelFavre, потому что он предназначен для кодирования всего URL, который не допускает использование таких символов, как :, /и @т. Д. Эти два метода не должны использоваться взаимозаменяемо, вы должны знать, что вы кодируете, чтобы использовать правильный метод.
Буу Нгуен
Как уже упоминалось в другом ответе на этой странице , этот сайт подробно описывает причину использования этого метода
Брэд Паркс
1523

У вас есть три варианта:

  • escape() не будет кодировать: @*/+

  • encodeURI() не будет кодировать: ~!@#$&*()=:/,;?+'

  • encodeURIComponent() не будет кодировать: ~!*()'

Но в вашем случае, если вы хотите передать URL в GETпараметр другой страницы, вы должны использовать escapeили encodeURIComponent, но не использовать encodeURI.

См. Вопрос о переполнении стека. Рекомендация : escape или encodeURI / encodeURIComponent для дальнейшего обсуждения.

CMS
источник
76
Кодировка символов, используемая с escape, является переменной. Палка с encodeURI и encodeURIComponent, которые используют UTF-8.
Эриксон
6
Быть осторожен. Этот escape преобразует не-ASCII символы в его escape-последовательности Unicode, например %uxxx.
opteronn
4
Я использую encodeURIComponent и заметил, что он не будет кодировать символы канала |
kevzettler
15
@kevzettler - зачем это делать? Каналы не имеют семантической важности в URI.
Ник
4
@GiovanniP: Люди, которые допускают ввод немецких, французских, японских, китайских, арабских символов и передают параметры тезисов через GET или POST.
Ценг
180

Придерживайтесь encodeURIComponent(). Функция encodeURI()не пытается кодировать много символов, имеющих семантическое значение в URL (например, «#», «?» И «&»).escape()устарела и не имеет смысла кодировать символы «+», которые будут интерпретироваться как закодированные пробелы на сервере (и, как указано другими здесь, неправильно кодирует URL-адреса не-ASCII-символов).

Есть хорошее объяснение разницы между encodeURI()и вencodeURIComponent() других местах. Если вы хотите что-то кодировать, чтобы его можно было безопасно включить в качестве компонента URI (например, в качестве параметра строки запроса), вы хотите использовать его encodeURIComponent().

Майк Бреннан
источник
83

Лучший ответ заключается в использовании encodeURIComponentна значениях в строке запроса (и нигде больше).

Тем не менее, я считаю, что многие API хотят заменить "" на "+", поэтому мне пришлось использовать следующее:

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

escape реализован по-разному в разных браузерах и encodeURI не кодирует много символов (например, # и даже /) - он предназначен для использования с полным URI / URL, не нарушая его - что не очень полезно и не безопасно.

И, как указывает @Jochem ниже, вы можете использовать имя encodeURIComponent()(каждой) папки, но по какой-то причине эти API-интерфейсы, кажется, не нуждаются +в именах папок, таких старыхencodeURIComponent отлично работают.

Пример:

const escapedValue = encodeURIComponent(value).replace('%20','+');
const escapedFolder = encodeURIComponent('My Folder'); // no replace
const url = `http://example.com/${escapedFolder}/?myKey=${escapedValue}`;
Райан Тейлор
источник
22
Обратите внимание, что вы должны заменять% 20 ​​на символы + только после первого вопросительного знака (который является частью URL-адреса запроса). Допустим, я хочу просмотреть http://somedomain/this dir has spaces/info.php?a=this has also spaces. Его следует преобразовать в: http://somedomain/this%20dir%20has%spaces/info.php?a=this%20has%20also%20spacesно многие реализации допускают замену «% 20» в строке запроса на «+». Тем не менее, вы не можете заменить «% 20» на «+» в разделе пути URL-адреса, это приведет к ошибке «Не найден», если у вас нет каталога с +пробелом.
Йохем Куиджперс
@Jochem Kuijpers, определенно, вы бы не поместили «+» в каталог. Я бы применил это только к самим значениям параметров запроса (или ключам, если необходимо), а не ко всему URL или даже всей строке запроса.
Райан Тейлор
Я бы заменил в значении, а не в результате кодировки
njzk2
1
@ njzk2, к сожалению encodeURIComponent('+'), даст вам %2B, так что вам придется использовать два регулярных выражения ... что, я полагаю, почему-то так работает, потому что '+' are '' в конце кодируются по-разному.
Райан Тейлор
Нет смысла переводить% 20 ​​в "+". Допустимая escape-последовательность для пространства ASCII:% 20, а не «+», что не упомянуто в RFC 3986 ( tools.ietf.org/html/rfc3986 ). «+» использовался в 1990-х годах; сейчас он устарел и поддерживается только по устаревшим причинам. Не используйте это.
Ксиенн
40

Если вы используете JQuery, я бы пошел на $.paramметод. Он URL кодирует поля сопоставления объектов со значениями, которые легче читать, чем вызывать метод escape для каждого значения.

$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1
Максим Козленко
источник
Я думаю, что приведенный пример является достаточным. Если вам нужна дополнительная информация о $ .param на api.jquery.com/jquery.param
Максим Козленко
Почти все используют jQuery, и я действительно чувствую себя более комфортно с этим, а не с компонентом uRIComponent
Кирилл Дюшон-Дорис
12

encodeURIComponent () - это путь.

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

НО вы должны иметь в виду, что есть небольшие отличия от версии 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', '+');
}
Адам Фишер
источник
10

Для кодирования URL, как уже было сказано, у вас есть две функции:

encodeURI()

а также

encodeURIComponent()

Причина обоих заключается в том, что первый сохраняет URL с риском оставить слишком много вещей без изменений, а второй кодирует все необходимое.

С первым вы можете скопировать недавно экранированный URL в адресную строку (например), и он будет работать. Однако ваши неэкранированные '&' будут мешать разделителям полей, '=' будут влиять на имена и значения полей, а '+' будут выглядеть как пробелы. Но для простых данных, когда вы хотите сохранить природу URL того, что вы избегаете, это работает.

Второе - это все, что вам нужно сделать, чтобы ничто в вашей строке не мешало URL. Это оставляет различные неважные символы без экранирования, так что URL остается максимально удобным для чтения человеком без помех. URL, закодированный таким образом, больше не будет работать как URL без его удаления.

Поэтому, если вы можете потратить время, вы всегда хотите использовать encodeURIComponent () - перед добавлением пар имя / значение кодируйте и имя, и значение, используя эту функцию, перед добавлением его в строку запроса.

Мне трудно найти причины для использования encodeURI () - я оставлю это более умным людям.

Жерар ОНЕЙЛ
источник
5

Подобные вещи я пробовал с обычным JavaScript

function fixedEncodeURIComponent(str){
     return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
}
Narayan Yerrabachu
источник
5

Элегантный способ

По моему скромному мнению, самый элегантный способ кодирования параметров запроса - создать объект с такими параметрами, как

const queryParams = { param1: 'value1', param2: 'value2' }

и затем закодируйте его, используя:

const queryString = new URLSearchParams(queryParams).toString()

как указано в этом ответе: https://stackoverflow.com/a/53171438/7284582

QBack
источник
4

Чтобы предотвратить двойное кодирование, рекомендуется декодировать URL-адрес перед кодированием (например, если вы имеете дело с введенными пользователем URL-адресами, которые могут быть уже закодированы).

Допустим, мы имеем в abc%20xyz 123качестве входных данных (один пробел уже закодирован):

encodeURI("abc%20xyz 123")            //   wrong: "abc%2520xyz%20123"
encodeURI(decodeURI("abc%20xyz 123")) // correct: "abc%20xyz%20123"
Serg
источник
4

Что такое кодировка URL:

URL-адрес должен быть закодирован, если в нем есть специальные символы. Например:

console.log(encodeURIComponent('?notEncoded=&+'));

В этом примере мы можем наблюдать, что все символы, кроме строки notEncoded, кодируются знаками%. Кодировка URL также называется процентной кодировкой поскольку она экранирует все специальные символы с помощью%. Затем после этого знака% каждый специальный символ имеет уникальный код

Зачем нам нужна кодировка URL:

Некоторые символы имеют специальное значение в строке URL. Например,? символ обозначает начало строки запроса. Чтобы успешно найти ресурс в сети, необходимо различать, когда символ подразумевается как часть строки или часть структуры URL.

Как мы можем добиться кодирования URL в JS:

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"));

Мы можем наблюдать, если мы поместим весь URL в encodeURIComponent том, что косые черты (/) также преобразуются в специальные символы. Это приведет к тому, что URL больше не будет работать должным образом.

Поэтому (как следует из названия) используйте:

  1. encodeURIComponent на определенной части URL, который вы хотите кодировать.
  2. encodeURI на весь URL, который вы хотите кодировать.
Виллем ван дер Веен
источник
3

У меня ничего не получалось. Я видел только HTML-код страницы входа, возвращаясь на клиентскую сторону с кодом 200. (Сначала 302, но тот же Ajax-запрос, загружающий страницу входа в другой Ajax-запрос, который должен был быть перенаправлением, а не простой загрузкой текст страницы входа).

В контроллере входа я добавил эту строку:

Response.Headers["land"] = "login";

И в глобальном обработчике Ajax я сделал это:

$(function () {
    var $document = $(document);
    $document.ajaxSuccess(function (e, response, request) {
        var land = response.getResponseHeader('land');
        var redrUrl = '/login?ReturnUrl=' + encodeURIComponent(window.location);
        if(land) {
            if (land.toString() === 'login') {
                window.location = redrUrl;
            }
        }
    });
});

Теперь у меня нет никаких проблем, и это работает как шарм.

Асиф Ашраф
источник
2

Кодировать строку URL

    var url = $ ( местоположение ). attr ( 'href' ); // получить текущий URL // ИЛИ var url = 'folder / index.html? param = # 23dd & noob = yes' ; // или указать один 
    
      

var encodedUrl = encodeURIComponent(url); console.log(encodedUrl); //outputs folder%2Findex.html%3Fparam%3D%2323dd%26noob%3Dyes for more info go http://www.sitepoint.com/jquery-decode-url-string
Сангит Шах
источник
2

Вот ЖИВОЙ DEMO из encodeURIComponent()и decodeURIComponent()JS встроенных функций:

<!DOCTYPE html>
<html>
  <head>
    <style>
      textarea{
        width:30%;
        height:100px;
      }
    </style>
    <script>
      // encode string to base64
      function encode()
      {
        var txt = document.getElementById("txt1").value;
        var result = btoa(txt);
        document.getElementById("txt2").value = result;
      }
      // decode base64 back to original string
      function decode()
      {
        var txt = document.getElementById("txt3").value;
        var result = atob(txt);
        document.getElementById("txt4").value = result;
      }
    </script>
  </head>
  <body>
    <div>
      <textarea id="txt1">Some text to decode
      </textarea>
    </div>
    <div>
      <input type="button" id="btnencode" value="Encode" onClick="encode()"/>
    </div>
    <div>
      <textarea id="txt2">
      </textarea>
    </div>
    <br/>
    <div>
      <textarea id="txt3">U29tZSB0ZXh0IHRvIGRlY29kZQ==
      </textarea>
    </div>
    <div>
      <input type="button" id="btndecode" value="Decode" onClick="decode()"/>
    </div>
    <div>
      <textarea id="txt4">
      </textarea>
    </div>
  </body>
</html>
jonathana
источник
1

Вы можете использовать библиотеку esapi и кодировать свой URL, используя функцию ниже. Функция гарантирует, что «/» не будут потеряны для кодирования, в то время как остальная часть текстового содержимого закодирована:

function encodeUrl(url)
{
    String arr[] = url.split("/");
    String encodedUrl = "";
    for(int i = 0; i<arr.length; i++)
    {
        encodedUrl = encodedUrl + ESAPI.encoder().encodeForHTML(ESAPI.encoder().encodeForURL(arr[i]));
        if(i<arr.length-1) encodedUrl = encodedUrl + "/";
    }
    return url;
}

https://www.owasp.org/index.php/ESAPI_JavaScript_Readme

Мохит Маратт
источник
1

Используйте fixedEncodeURIComponentфункцию для строгого соответствия RFC 3986 :

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
Артур
источник
1

Вы не должны использовать encodeURIComponent()напрямую.

Взгляните на RFC3986: унифицированный идентификатор ресурса (URI): общий синтаксис

sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" знак равно

Назначение зарезервированных символов - предоставить набор символов-разделителей, которые можно отличить от других данных в URI.

Эти зарезервированные символы из определения URI в RFC3986 НЕ экранированы encodeURIComponent().

MDN Web Docs: encodeURIComponent ()

Чтобы быть более строгими в соблюдении RFC 3986 (который резервирует!, ', (,) И *), даже если эти символы не имеют формализованного использования в качестве разделителя URI, можно безопасно использовать следующее:

Используйте функцию MDN Web Docs ...

function fixedEncodeURIComponent(str) {
  return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
    return '%' + c.charCodeAt(0).toString(16);
  });
}
HoldOffHunger
источник