Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't the protocol of an URL object be changed for non-http(s) URLs in JavaScript?

Tags:

javascript

url

In JavaScript, there seems to be some restrictions when changing the protocol of a given URL when using the URL object. However, I can't find where this behaviour is documented (URL, URL.prototype.protocol) or why it would be intended for it to work like that.

Can anyone shine some light on this?

EDIT: The behaviour seems to be inconsistent across JS runtimes. Firefox, Node and Deno all "refuse" to change the protocol, but Chrome, Safari and Bun all "comply" with the change…

const url1 = new URL('http://example.com')
console.log(url1.protocol) // http:
url1.protocol = 'https:'
console.log(url1.protocol) // https:

const url2 = new URL('webcal://example.com')
console.log(url2.protocol) // webcal:
url2.protocol = 'https:'
console.log(url2.protocol) // webcal:, but should be https:
like image 517
Samuel Martineau Avatar asked Oct 20 '25 15:10

Samuel Martineau


1 Answers

This is documented for Node.js:

The WHATWG URL Standard considers a handful of URL protocol schemes to be special in terms of how they are parsed and serialized. When a URL is parsed using one of these special protocols, the url.protocol property may be changed to another special protocol but cannot be changed to a non-special protocol, and vice versa.

For instance, changing from http to https works: […]

However, changing from http to a hypothetical fish protocol does not because the new protocol is not special. […]

Likewise, changing from a non-special protocol to a special protocol is also not permitted: […]

According to the WHATWG URL Standard, special protocol schemes are ftp, file, http, https, ws, and wss.

(emphasis and ellipsis mine)

Your webcal protocol is not in that list, so you cannot change it to https.

The intention of distinguishing special from non-special URLs appears to be that their hostname should be parsed differently, e.g. requiring valid domain names. That makes switching protocols a hazard if the hostname of the existing URL does not satisfy the requirements of the new protocol.

For Node.js, this is implemented by the C++ Ada URL library. Deno uses the Rust urlpattern crate. Firefox already changed their implementation to comply with the spec, Chrome followed just recently and will release this with M118. The Webkit (Safari, Bun) bug report is still open.

Still, this is bonkers, and there is a specification issue opened in 2021 to allow this. There also might be web compatibility issues with this restriction, so they may have to adjust the spec instead. However, it appears that the current plan is to follow through with it, and instead add a constructor for creating a new URL from parts.

like image 192
Bergi Avatar answered Oct 22 '25 03:10

Bergi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!