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

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

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

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

Попробуйте заглянуть в encodeURI () и decodeURI ().

Zack The Human 02.12.2008 05:39

Вы можете использовать этот инструмент здесь: phillihp.com/toolz/url-encode-decode

phillihp 18.09.2012 06:13

См. Функция urlencode JavaScript.

Yanni 30.06.2011 20:40

encodeURIComponent ()

Andrew 02.03.2018 21:52
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2 581
4
1 601 381
20
Перейти к ответу Данный вопрос помечен как решенный

Ответы 20

Ответ принят как подходящий

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

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

Как насчет добавления объяснения, которое дал @cms? escape также является допустимым вариантом.

hitautodestruct 28.10.2012 15:36

согласно @CMS encodeURI не совсем безопасен для кодирования URL.

Ifnot 01.03.2013 20:35

@AnaelFavre, потому что он предназначен для кодирования всего URL-адреса, что не позволяет использовать такие символы, как :, /, @ и т. д. Эти 2 метода нельзя использовать взаимозаменяемо, вы должны знать, что кодируете, чтобы использовать правильный метод.

Buu Nguyen 06.03.2013 23:32

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

Brad Parks 06.05.2016 16:07

@BuuNguyen это не работает для меня. Я все еще вижу значок & as & amp; в моем терминале.

node_saini 17.10.2016 17:31

@BuuNguyen: Привет, BuuNguyen, спасибо за полезное решение. пожалуйста, подтвердите меня? Могу ли я использовать метод encodeURIComponent () для кодирования простой строки, потому что в моем приложении я добавляю строковое содержимое непосредственно как значение для запроса строкового ключа, а затем его ведущую проблему XSS. это мой код var mywindow = window .open( "https://" + window.location.host + "center/js/cal.html?context = " + conString + "&date = " + dateString + "&firstName = " + firstName);

Venki 15.12.2016 12:23

@BuuNguyen: Теперь говорится, что &firstName может быть причиной проблемы с XSS. Что мне теперь делать? если я закодирую firstname, то он разрешится или нет? пожалуйста, предложите мне что-нибудь. Ty.

Venki 15.12.2016 12:28

Есть много хороших сайтов, которые позволят вам поиграть с этим: string-io.com - один из них.

germs12 21.07.2017 01:08

Мне пришлось передать номер +39123.. со знаком плюса: encodeURI() работал, но мой бэкэнд его не видел, в то время как encodeURIComponent() преуспел (в angular 8 и asp.net core 3)

Biiz 11.06.2020 14:29

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

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

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

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

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

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

Кодировка символов, используемая с escape-символом, является переменной. Придерживайтесь encodeURI и encodeURIComponent, которые используют UTF-8.

erickson 02.12.2008 07:55

Я использую encodeURIComponent и заметил, что он не кодирует вертикальные символы |

kevzettler 30.01.2011 08:05

@kevzettler - зачем ему это делать? Каналы не имеют семантического значения в URI.

nickf 31.01.2011 14:36

Будь осторожен. Этот escape-код преобразует символы, отличные от ASCII, в escape-последовательности Unicode, такие как %uxxx.

opteronn 05.03.2010 23:10

Кто-нибудь использует символы, отличные от ASCII, в URI?

fiatjaf 06.07.2013 01:45

@GiovanniP: люди, которые разрешают вводить немецкие, французские, японские, китайские, арабские символы и передавать эти параметры через GET или POST.

Tseng 04.09.2013 18:43

ах, хорошо, я думал, вы говорите о частях домена / пути, не знаю, почему я так подумал.

fiatjaf 21.09.2013 03:18
encodeURIComponent() кодировал #, а encodeURI() - нет!
John N 29.10.2014 22:30

@fiatjaf Символы, отличные от ASCII, также вполне допустимы в доменах, хотя в системе DNS будет храниться версия ASCII. en.wikipedia.org/wiki/Internationalized_domain_name

Thor84no 03.11.2014 22:12

ПРИМЕЧАНИЕ. Начиная с версии 1.5 JavaScript escape () устарел. Придерживайтесь либо encodeURI (), либо encodeComponent (). developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…

Dzeimsas Zvirblis 16.12.2015 18:42

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

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

У меня ничего не работало. Все, что я видел, - это 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;
            }
        }
    });
});

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

Лучший ответ - использовать 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}`;

Обратите внимание, что вам следует заменять% 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%20‌​has%20also%20spaces, но многие реализации позволяют заменять «% 20» в строке запроса на «+». Тем не менее, вы не можете заменить «% 20» на «+» в разделе пути URL-адреса, это приведет к ошибке «Не найдено», если у вас нет каталога с + вместо пробела.

Jochem Kuijpers 20.01.2013 05:08

@Jochem Kuijpers, определенно, вы не стали бы помещать "+" в каталог. Я бы применил это только к самим значениям параметров запроса (или ключам, если необходимо), а не ко всему URL-адресу или даже ко всей строке запроса.

Ryan Taylor 20.07.2013 02:16

Я бы заменил по значению, а не по результату кодирования

njzk2 02.06.2014 22:11

@ njzk2, к сожалению, encodeURIComponent('+') даст вам %2B, поэтому вам придется использовать два регулярных выражения ... что, я полагаю, отчасти почему это работает, потому что '+' are '' в конце кодируются по-разному.

Ryan Taylor 02.06.2014 22:17

Нет причин переводить% 20 ​​в "+". Допустимая escape-последовательность для пространства ASCII -% 20, а не «+», который не упоминается в RFC 3986 (tools.ietf.org/html/rfc3986). «+» использовалось в 1990-х годах; Сейчас он устарел и поддерживается только по устаревшим причинам. Не используйте это.

xhienne 26.03.2019 15:25

@xhienne наверняка, это просто то, что я заметил в реальном мире на нескольких API, всегда было бы разумнее использовать encodeURIComponent, когда это работает - было бы неплохо, если бы люди могли придерживаться одного стандарта! И желательно спецификацию RFC.

Ryan Taylor 26.03.2019 18:20

Независимо от того, это a + или% 20, декодирующий компонент должен знать, как интерпретировать любое значение и создавать пробел. Только спецификации, такие как oauth, требуют закодированных строк в своей спецификации, где это имеет значение.

Gerard ONeill 25.04.2019 23:23

Я бы посоветовал использовать пакет qs npm

qs.stringify({a:"1=2", b:"Test 1"}); // gets a=1%3D2&b=Test+1

его проще использовать с объектом JS, и он дает вам правильную кодировку URL для всех параметров

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

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

Я думаю, что приведенного примера достаточно. Если вам нужна дополнительная информация о $ .param на api.jquery.com/jquery.param

Maksym Kozlenko 10.09.2015 13:21

Практически все используют jQuery, и я чувствую себя более комфортно с этим вместо encoreURIComponent

Cyril Duchon-Doris 04.01.2017 19:36

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

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

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

    var url = $(location).attr('href'); //get current url
    //OR
    var url = 'folder/index.html?param=#23dd&noob=yes'; //or specify one

var encodedUrl = encodeURIComponent(url);
console.info(encodedUrl);
//outputs folder%2Findex.html%3Fparam%3D%2323dd%26noob%3Dyes


for more info go http://www.sitepoint.com/jquery-decode-url-string

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', '+');
}

Вы можете использовать библиотеку 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

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

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

encodeURI("abc%20xyz 123")            //   wrong: "abc%2520xyz%20123"
encodeURI(decodeURI("abc%20xyz 123")) // correct: "abc%20xyz%20123"

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

encodeURI()

и

encodeURIComponent()

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

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

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

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

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

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

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

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

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

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

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

Как добиться кодировки URL в JS:

JS предлагает набор встроенных служебных функций, которые мы можем использовать для простого кодирования URL-адресов. Это два удобных варианта:

  1. encodeURIComponent(): принимает компонент URI в качестве аргумента и возвращает закодированную строку URI.
  2. encodeURI(): принимает URI в качестве аргумента и возвращает закодированную строку URI.

Пример и предостережения:

Помните, что в encodeURIComponent() нельзя передавать весь URL-адрес (включая схему, например https: //). Это может фактически превратить его в неработающий URL. Например:

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

// instead use encodeURI for whole URL's
console.info(encodeURI("http://www.random.com/specials&char.html"));

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

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

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

Вот ЖИВАЯ ДЕМО встроенных функций 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>

Используйте функцию fixedEncodeURIComponent, чтобы строго соблюдать RFC 3986:

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

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

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

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

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

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

как упоминалось в этом ответе: https://stackoverflow.com/a/53171438/7284582

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

Взгляните на RFC3986: Uniform Resource Identifier (URI): Generic Syntax

sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / " = "

The purpose of reserved characters is to provide a set of delimiting characters that are distinguishable from other data within a URI.

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

Веб-документы MDN: encodeURIComponent ()

To be more stringent in adhering to RFC 3986 (which reserves !, ', (, ), and *), even though these characters have no formalized URI delimiting uses, the following can be safely used:

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

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

Представление

Сегодня (2020.06.12) я провожу тест скорости выбранных решений на MacOs HighSierra 10.13.6 в браузерах Chrome 83.0, Safari 13.1, Firefox 77.0. Эти результаты могут быть полезны для массового кодирования URL-адресов.

Выводы

  • encodeURI (B) кажется самым быстрым, но это не рекомендуется для url-ов
  • escape (A) - быстрое кросс-браузерное решение
  • решение F, рекомендованное MDN, является средне быстрым
  • решение D самое медленное

Подробности

Для решений АBCDEF Я провожу два теста

  • для короткого url - 50 символов - можно запустить ЗДЕСЬ
  • для длинного url - 1M char - можно запустить ЗДЕСЬ

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.info(`${f.name} ?url=${f(myUrl).replace(/^url=/,'')}`));
This snippet only presents code of choosen solutions

Примеры результатов для Chrome

var myOtherUrl = 
   "http://example.com/index.html?url = " + encodeURIComponent(myUrl).replace(/%20/g,'+');

Не забудьте флаг / g, чтобы заменить все закодированные ''

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

function urlEncode(text) {
    encoded = '';
    for (let char of text) {
        encoded += '%' + char.charCodeAt(0).toString(16);
    }
    return encoded;
}

Другие вопросы по теме