loading...

encodeURIComponent is both not safe enough, and overdone

patarapolw profile image Pacharapol Withayasakpunt Updated on ・1 min read

I have tested with encodeURIComponent, decodeURIComponent and URL constructor, and the results are

{
  "pathname": {
    "destroyed": " #.?",
    "encoded": "\"<>`{}",
    "error": {
      "Invalid URL: //": "/",
      "Invalid URL: /\\": "\\"
    }
  },
  "key": {
    "destroyed": "#&+="
  },
  "value": {
    "destroyed": " #&+"
  },
  "hash": {
    "destroyed": " ",
    "encoded": "\"<>`"
  },
  // /[A-Za-z0-9]/ are excluded.
  "notEncoded": {
    "encodeURI": "!#$&'()*+,-./:;=?@_~",
    "encodeURIComponent": "!'()*-._~",
    "escape": "*+-./@_"
  }
  // encoded with `%${x.charCodeAt(0).toString(16).toUpperCase()}`
  "notDecoded": {
    "decodeURI": "#$&+,/:;=?@"
  }
}

The test is here.

So,

  • Reserved characters ;,/?:@&=+$ are not equal. Some are allowed in some scenarios, some are not. And it seems that encodeURI is never safe to encode a URI segment.
  • Path params, e.g. /:segment/* on the server
    • ., .. always have wrong meanings, whether percent-encoded or not. And encodeURIComponent('.') is indeed .. /^\.{3,}$/ are ok, though.
      • It seems that escaping by prefixing with ~ is enough.
    • /, even when encoded, may throw error on some server. Not sure about \, but it seems to throw error in my test.
  • Luckily, these are always encoded. I have seen a recent post about the errors.
"<>`{}
  • Not sure if non-ASCII (/[^\x00-\x7F]/) needs to be encoded. You can try it in my demo, and see if it breaks.

https://encodeuri-plus.netlify.app/

So, I created a library for this,

GitHub logo patarapolw / encodeuri-plus

encodeURI that is safe, and doesn't do too much in a specific scenario

Republished in my blog

Posted on by:

patarapolw profile

Pacharapol Withayasakpunt

@patarapolw

Currently interested in TypeScript, Vue, Kotlin and Python. Looking forward to learning DevOps, though.

Discussion

markdown guide