it-swarm-ru.tech

Когда вы должны использовать escape вместо encodeURI/encodeURIComponent?

При кодировании строки запроса для отправки на веб-сервер - когда вы используете escape() и когда вы используете encodeURI() или encodeURIComponent():

Используйте escape:

escape("% +&=");

OR

используйте encodeURI ()/encodeURIComponent ()

encodeURI("http://www.google.com?var1=value1&var2=value2");

encodeURIComponent("var1=value1&var2=value2");
1323
Adam

побег()

Не используйте его! escape() определена в разделе B.2.1.2 escape , а текст вводной части Приложения B гласит:

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

Поведение:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape

Специальные символы кодируются за исключением: @ * _ + -. /

Шестнадцатеричная форма для символов, значение кодовой единицы которых равно 0xFF или меньше, представляет собой двузначную escape-последовательность: %xx.

Для символов с большей единицей кода используется четырехзначный формат %uxxxx. Это недопустимо в строке запроса (как определено в RFC3986 ):

query       = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
              / "*" / "+" / "," / ";" / "="

Знак процента допускается только в том случае, если за ним сразу следуют две шестнадцатеричные цифры, а процент с последующим u не допускается.

encodeURI ()

Используйте encodeURI, когда вы хотите рабочий URL. Сделайте этот звонок:

encodeURI("http://www.example.org/a file with spaces.html")

получить:

http://www.example.org/a%20file%20with%20spaces.html

Не вызывайте encodeURIComponent, поскольку он уничтожит URL и вернет

http%3A%2F%2Fwww.example.org%2Fa%20file%20with%20spaces.html

encodeURIComponent ()

Используйте encodeURIComponent, когда вы хотите закодировать значение параметра URL.

var p1 = encodeURIComponent("http://example.org/?a=12&b=55")

Затем вы можете создать нужный вам URL:

var url = "http://example.net/?param1=" + p1 + "&param2=99";

И вы получите этот полный URL:

http://example.net/?param1=http%3A%2F%2Fexample.org%2F%Ffa%3D12%26b%3D55&param2=99

Обратите внимание, что encodeURIComponent не экранирует символ '. Распространенной ошибкой является использование ее для создания атрибутов html, таких как href='MyUrl', что может привести к ошибке внедрения. Если вы строите html из строк, либо используйте " вместо ' для атрибутных кавычек, либо добавьте дополнительный уровень кодирования (' можно кодировать как% 27).

Для получения дополнительной информации об этом типе кодировки вы можете проверить: http://en.wikipedia.org/wiki/Percent-encoding

1847
Arne Evertsson

Разница между encodeURI() и encodeURIComponent() составляет ровно 11 символов, закодированных с помощью encodeURIComponent, но не с помощью encodeURI:

Table with the ten differences between encodeURI and encodeURIComponent

Я сгенерировал эту таблицу легко с console.table в Google Chrome с этим кодом:

var arr = [];
for(var i=0;i<256;i++) {
  var char=String.fromCharCode(i);
  if(encodeURI(char)!==encodeURIComponent(char)) {
    arr.Push({
      character:char,
      encodeURI:encodeURI(char),
      encodeURIComponent:encodeURIComponent(char)
    });
  }
}
console.table(arr);

411
Johann Echavarria

Я нашел эту статью поучительной: Javascript Madness: запрос разбора строк

Я обнаружил это, когда пытался понять, почему decodeURIComponent неправильно декодирует «+». Вот выдержка:

String:                         "A + B"
Expected Query String Encoding: "A+%2B+B"
escape("A + B") =               "A%20+%20B"     Wrong!
encodeURI("A + B") =            "A%20+%20B"     Wrong!
encodeURIComponent("A + B") =   "A%20%2B%20B"   Acceptable, but strange

Encoded String:                 "A+%2B+B"
Expected Decoding:              "A + B"
unescape("A+%2B+B") =           "A+++B"       Wrong!
decodeURI("A+%2B+B") =          "A+++B"       Wrong!
decodeURIComponent("A+%2B+B") = "A+++B"       Wrong!
43
Damien

encodeURIComponent не кодирует -_.!~*'(), вызывая проблему при публикации данных на php в строке xml.

Например:
<xml><text x="100" y="150" value="It's a value with single quote" /> </xml>

Общий побег с encodeURI
%3Cxml%3E%3Ctext%20x=%22100%22%20y=%22150%22%20value=%22It's%20a%20value%20with%20single%20quote%22%20/%3E%20%3C/xml%3E

Как видите, одинарная кавычка не закодирована . Чтобы решить проблему, я создал две функции для решения проблемы в своем проекте для URL кодирования:

function encodeData(s:String):String{
    return encodeURIComponent(s).replace(/\-/g, "%2D").replace(/\_/g, "%5F").replace(/\./g, "%2E").replace(/\!/g, "%21").replace(/\~/g, "%7E").replace(/\*/g, "%2A").replace(/\'/g, "%27").replace(/\(/g, "%28").replace(/\)/g, "%29");
}

Для декодирования URL:

function decodeData(s:String):String{
    try{
        return decodeURIComponent(s.replace(/\%2D/g, "-").replace(/\%5F/g, "_").replace(/\%2E/g, ".").replace(/\%21/g, "!").replace(/\%7E/g, "~").replace(/\%2A/g, "*").replace(/\%27/g, "'").replace(/\%28/g, "(").replace(/\%29/g, ")"));
    }catch (e:Error) {
    }
    return "";
}
38
Kirankumar Sripati

encodeURI () - функция escape () предназначена для экранирования JavaScript, а не HTTP.

37
Daniel Papasian

Небольшая таблица сравнения Java против JavaScript против PHP.

1. Java URLEncoder.encode (using UTF8 charset)
2. JavaScript encodeURIComponent
3. JavaScript escape
4. PHP urlencode
5. PHP rawurlencode

char   Java JavaScript --PHP---
[ ]     +    %20  %20  +    %20
[!]     %21  !    %21  %21  %21
[*]     *    *    *    %2A  %2A
[']     %27  '    %27  %27  %27 
[(]     %28  (    %28  %28  %28
[)]     %29  )    %29  %29  %29
[;]     %3B  %3B  %3B  %3B  %3B
[:]     %3A  %3A  %3A  %3A  %3A
[@]     %40  %40  @    %40  %40
[&]     %26  %26  %26  %26  %26
[=]     %3D  %3D  %3D  %3D  %3D
[+]     %2B  %2B  +    %2B  %2B
[$]     %24  %24  %24  %24  %24
[,]     %2C  %2C  %2C  %2C  %2C
[/]     %2F  %2F  /    %2F  %2F
[?]     %3F  %3F  %3F  %3F  %3F
[#]     %23  %23  %23  %23  %23
[[]     %5B  %5B  %5B  %5B  %5B
[]]     %5D  %5D  %5D  %5D  %5D
----------------------------------------
[~]     %7E  ~    %7E  %7E  ~
[-]     -    -    -    -    -
[_]     _    _    _    _    _
[%]     %25  %25  %25  %25  %25
[\]     %5C  %5C  %5C  %5C  %5C
----------------------------------------
char  -Java-  --JavaScript--  -----PHP------
[ä]   %C3%A4  %C3%A4  %E4     %C3%A4  %C3%A4
[ф]   %D1%84  %D1%84  %u0444  %D1%84  %D1%84
16
30thh

Я рекомендую не использовать один из этих методов как есть. Напишите свою собственную функцию, которая делает правильные вещи.

MDN привел хороший пример кодирования URL, показанный ниже.

var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''" + encodeRFC5987ValueChars(fileName);

console.log(header); 
// logs "Content-Disposition: attachment; filename*=UTF-8''my%20file%282%29.txt"


function encodeRFC5987ValueChars (str) {
    return encodeURIComponent(str).
        // Note that although RFC3986 reserves "!", RFC5987 does not,
        // so we do not need to escape it
        replace(/['()]/g, escape). // i.e., %27 %28 %29
        replace(/\*/g, '%2A').
            // The following are not required for percent-encoding per RFC5987, 
            //  so we can allow for a little better readability over the wire: |`^
            replace(/%(?:7C|60|5E)/g, unescape);
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent

11
Jerry Joseph

Также помните, что все они кодируют разные наборы символов, и выберите тот, который вам нужен. encodeURI () кодирует меньше символов, чем encodeURIComponent (), который кодирует меньше (и также отличается от точки Даннипа) символов, чем escape ().

10
Pseudo Masochist

Для целей кодирования javascript предоставил три встроенные функции -

  1. escape () - не кодирует @*/+ Этот метод считается устаревшим после ECMA 3, поэтому его следует избегать.

  2. encodeURI () - не кодирует [email protected]#$&*()=:/,;?+' Предполагается, что URI является полным URI, поэтому не кодирует зарезервированные символы, имеющие особое значение в URI . Этот метод используется, когда целью является преобразование полного URL вместо какого-то специального сегмента URL . Пример - encodeURI('http://stackoverflow.com'); Даст - http://stackoverflow.com

  3. encodeURIComponent () - не кодирует - _ . ! ~ * ' ( ) Эта функция кодирует компонент универсального идентификатора ресурса (URI), заменяя каждый экземпляр определенных символов одной, двумя, тремя или четырьмя escape-последовательностями, представляющими кодировку UTF-8 символа. Этот метод должен использоваться для преобразования компонента URL. Например, необходимо добавить некоторый пользовательский ввод Пример - encodeURI('http://stackoverflow.com'); Выдаст - http% 3A% 2F% 2Fstackoverflow.com

Вся эта кодировка выполняется в UTF 8, т. Е. Символы будут преобразованы в формат UTF-8. 

encodeURIComponent отличается от encodeURI тем, что он кодирует зарезервированные символы и номер знака # encodeURI

6
Gaurav Tiwari

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

С этой целью я нашел этот сайт чрезвычайно полезным, чтобы подтвердить мои подозрения, что я что-то делаю надлежащим образом. Это также оказалось полезным для декодирования строки, кодируемой encodeURIComponent, которую может быть довольно сложно интерпретировать. Отличная закладка, чтобы иметь:

http://www.the-art-of-web.com/javascript/escape/

3
veeTrain

У меня есть эта функция ...

var escapeURIparam = function(url) {
    if (encodeURIComponent) url = encodeURIComponent(url);
    else if (encodeURI) url = encodeURI(url);
    else url = escape(url);
    url = url.replace(/\+/g, '%2B'); // Force the replacement of "+"
    return url;
};
1
molokoloco

Принятый ответ хорош . Продолжим на последней части:

Обратите внимание, что encodeURIComponent не экранирует символ '. Обычный ошибка заключается в том, чтобы использовать его для создания атрибутов HTML, таких как href = 'MyUrl', который может пострадать ошибка инъекции. Если вы строите HTML из в строках, либо используйте «вместо» для кавычек атрибутов, либо добавьте дополнительный уровень кодировки (можно кодировать как% 27).

Если вы хотите быть в безопасности, процент кодирования незарезервированных символов также должен быть закодирован. 

Вы можете использовать этот метод, чтобы избежать их (источник Mozilla )

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

// fixedEncodeURIComponent("'") --> "%27"
1
Michael

Современное переписывание ответа @ johann-echavarria:

console.log(
    Array(256)
        .fill()
        .map((ignore, i) => String.fromCharCode(i))
        .filter(
            (char) =>
                encodeURI(char) !== encodeURIComponent(char)
                    ? {
                          character: char,
                          encodeURI: encodeURI(char),
                          encodeURIComponent: encodeURIComponent(char)
                      }
                    : false
        )
)

Или, если вы можете использовать таблицу, замените console.log на console.table (для более красивого вывода).

1
ryanpcmcquen

Вдохновленный стол Иоганна , я решил расширить стол. Я хотел посмотреть, какие символы ASCII кодируются.

 screenshot of console.table

var ascii = " !\"#$%&'()*+,-./0123456789:;<=>[email protected][\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

var encoded = [];

ascii.split("").forEach(function (char) {
    var obj = { char };
    if (char != encodeURI(char))
        obj.encodeURI = encodeURI(char);
    if (char != encodeURIComponent(char))
        obj.encodeURIComponent = encodeURIComponent(char);
    if (obj.encodeURI || obj.encodeURIComponent)
        encoded.Push(obj);
});

console.table(encoded);

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


Просто чтобы добавить, я добавляю еще одну таблицу для urlencode() vs rawurlencode() . Кажется, единственная разница заключается в кодировке пробела.

 screenshot of console.table

<script>
<?php
$ascii = str_split(" !\"#$%&'()*+,-./0123456789:;<=>[email protected][\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 1);
$encoded = [];
foreach ($ascii as $char) {
    $obj = ["char" => $char];
    if ($char != urlencode($char))
        $obj["urlencode"] = urlencode($char);
    if ($char != rawurlencode($char))
        $obj["rawurlencode"] = rawurlencode($char);
    if (isset($obj["rawurlencode"]) || isset($obj["rawurlencode"]))
        $encoded[] = $obj;
}
echo "var encoded = " . json_encode($encoded) . ";";
?>
console.table(encoded);
</script>
0
akinuri