When are you supposed to use escape instead of encodeURI / encodeURIComponent?

前端 未结 15 1154
栀梦
栀梦 2020-11-21 07:39

When encoding a query string to be sent to a web server - when do you use escape() and when do you use encodeURI() or encodeURIComponent()

相关标签:
15条回答
  • 2020-11-21 07:42

    The accepted answer is good. To extend on the last part:

    Note that encodeURIComponent does not escape the ' character. A common bug is to use it to create html attributes such as href='MyUrl', which could suffer an injection bug. If you are constructing html from strings, either use " instead of ' for attribute quotes, or add an extra layer of encoding (' can be encoded as %27).

    If you want to be on the safe side, percent encoding unreserved characters should be encoded as well.

    You can use this method to escape them (source Mozilla)

    function fixedEncodeURIComponent(str) {
      return encodeURIComponent(str).replace(/[!'()*]/g, function(c) {
        return '%' + c.charCodeAt(0).toString(16);
      });
    }
    
    // fixedEncodeURIComponent("'") --> "%27"
    
    0 讨论(0)
  • 2020-11-21 07:45

    I found this article enlightening : Javascript Madness: Query String Parsing

    I found it when I was trying to undersand why decodeURIComponent was not decoding '+' correctly. Here is an extract:

    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!
    
    0 讨论(0)
  • 2020-11-21 07:46

    escape()

    Don't use it! escape() is defined in section B.2.1.2 escape and the introduction text of Annex B says:

    ... All of the language features and behaviours specified in this annex have one or more undesirable characteristics and in the absence of legacy usage would be removed from this specification. ...
    ... Programmers should not use or assume the existence of these features and behaviours when writing new ECMAScript code....

    Behaviour:

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

    Special characters are encoded with the exception of: @*_+-./

    The hexadecimal form for characters, whose code unit value is 0xFF or less, is a two-digit escape sequence: %xx.

    For characters with a greater code unit, the four-digit format %uxxxx is used. This is not allowed within a query string (as defined in RFC3986):

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

    A percent sign is only allowed if it is directly followed by two hexdigits, percent followed by u is not allowed.

    encodeURI()

    Use encodeURI when you want a working URL. Make this call:

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

    to get:

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

    Don't call encodeURIComponent since it would destroy the URL and return

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

    Note that encodeURI, like encodeURIComponent, does not escape the ' character.

    encodeURIComponent()

    Use encodeURIComponent when you want to encode the value of a URL parameter.

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

    Then you may create the URL you need:

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

    And you will get this complete URL:

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

    Note that encodeURIComponent does not escape the ' character. A common bug is to use it to create html attributes such as href='MyUrl', which could suffer an injection bug. If you are constructing html from strings, either use " instead of ' for attribute quotes, or add an extra layer of encoding (' can be encoded as %27).

    For more information on this type of encoding you can check: http://en.wikipedia.org/wiki/Percent-encoding

    0 讨论(0)
  • 2020-11-21 07:48

    Modern rewrite of @johann-echavarria's answer:

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

    Or if you can use a table, replace console.log with console.table (for the prettier output).

    0 讨论(0)
  • 2020-11-21 07:51

    I've found that experimenting with the various methods is a good sanity check even after having a good handle of what their various uses and capabilities are.

    Towards that end I have found this website extremely useful to confirm my suspicions that I am doing something appropriately. It has also proven useful for decoding an encodeURIComponent'ed string which can be rather challenging to interpret. A great bookmark to have:

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

    0 讨论(0)
  • 2020-11-21 07:51

    I have this function...

    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;
    };
    
    0 讨论(0)
提交回复
热议问题