Why doesn't the URL constructor encode parentheses in the query string?
P粉287254588
2023-09-03 21:05:00
<p>In JavaScript, the <code>URL</code> constructor does not encode brackets and parentheses when they appear in a query string, while <code>encodeURI</code> or <code>encodeURIComponent</code> will always encode them. This confuses me because most sources say to use <code>encodeURI</code>/<code>encodeURIComponent</code> to encode when special characters are included in query parameters. I expected similar behavior for the <code>URL</code> object. </p>
<p>This causes me to have problems writing unit tests because I don't know how the URL object's query parameters will be encoded. Is there a specification that states this, or should I always encode parameters before using the <code>URL</code> constructor? thank you for your help. </p>
<hr />
<p>Example showing URL object not encoding brackets in query string</p>
<pre class="brush:js;toolbar:false;">const href = (new URL('https://foobar.com?myQuery={"@asdf/asdf":"1234"}' )).href;
// ^ https://foobar.com/?myQuery={"@asdf/asdf":"1234"}
</pre>
<p>If I use <code>encodeURI</code>, the only difference is that the brackets are encoded</p>
<pre class="brush:js;toolbar:false;">const href = encodeURI('https://foobar.com?myQuery={"@asdf/asdf":"1234"}');
// ^ https://foobar.com?myQuery={"@asdf/asdf":"1234"}
</pre>
<hr />
<p>Note: If the parentheses are not in the query parameters, the URL object will encode them. </p>
<pre class="brush:js;toolbar:false;">const href = (new URL('https://foobar.com/}}}?myQuery={"@asdf/asdf":" 1234"}')).href;
// ^ https://foobar.com/}}}?myQuery={"@asdf/asdf":"1234"}
</pre></p>
There are multiple possible encodings, they should all be interpreted as the same URL, so none are technically wrong. Another example is that percent encoding can use uppercase or lowercase characters (
or
(in some parts).
�
or�
), domain names are not case-sensitive, and spaces can be encoded asIf you want to unit test a specific implementation of URL encoding, you can do string matching, but if you want to know if two URLs are the same regardless of how they are encoded, you first need to do a step called "canonicalization" operation and then compare.