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

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

2308 голосов
/ 02 декабря 2008

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

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

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

Ответы [ 14 ]

2656 голосов
/ 02 декабря 2008

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

var myOtherUrl = 
       "http://example.com/index.html?url=" + encodeURIComponent(myUrl);
1457 голосов
/ 02 декабря 2008

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

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

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

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

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

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

171 голосов
/ 30 мая 2011

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

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

76 голосов
/ 15 декабря 2012

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

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

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

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

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

Пример:

const escapedValue = encodeURIComponent(value).replace(/%20/g,'+');
const escapedFolder = encodeURIComponent('My Folder'); // no replace
const url = `http://example.com/${escapedFolder}/?myKey=${escapedValue}`;
39 голосов
/ 13 мая 2013

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

$.param({a:"1=2", b:"Test 1"}) // gets a=1%3D2&b=Test+1
10 голосов
/ 27 января 2017

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

encodeURI()

и

encodeURIComponent()

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

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

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

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

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

9 голосов
/ 01 октября 2015

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(/!/g, '%21')
    .replace(/'/g, '%27')
    .replace(/\(/g, '%28')
    .replace(/\)/g, '%29')
    .replace(/\*/g, '%2A')
    .replace(/%20/g, '+');
}
5 голосов
/ 14 мая 2013

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

function fixedEncodeURIComponent(str){
     return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
}
4 голосов
/ 05 января 2017

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

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

encodeURI("abc%20xyz 123")            //   wrong: "abc%2520xyz%20123"
encodeURI(decodeURI("abc%20xyz 123")) // correct: "abc%20xyz%20123"
3 голосов
/ 22 июня 2012

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...