-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
Hi, I am getting an exception when connecting to IPv6 localhost address ::1
I have found this was reported and fixed in #1130 / #1147 (commit 70a247c) however it seems to have been reverted and the current V4.3.7 is once more using the depreciated url.parse as you can see here: https://github.com/mqttjs/MQTT.js/blob/main/lib/connect/index.js#L64
Here is a minimal repro...
const userEnteredURL = 'ws://[::1]:8883'
const client = mqtt.connect(userEnteredURL, this.brokerConfig)Here is why I think the underlying issue exists: mqtt.js manually rebuilds the broker URL using hostname + port in
https://github.com/mqttjs/MQTT.js/blob/main/lib/connect/ws.js#L20
let url = opts.protocol + '://' + opts.hostname + ':' + opts.port + opts.path
... but, url.parse().hostname drops the squarebrackets off [::1] which causes the above code to generate the url http://::1:8883. Further downstream, the ws package uses new URL(...) with this re-assembled URL string & the ERR_INVALID_URL error occurs.
For anyone else reading, here is a minimal (hacky) workaround...
const userEnteredURL = 'ws://[::1]:8883'
const tempNewURL= new URL(userEnteredURL)
const brokerURL = url.parse(userEnteredURL)
brokerURL.hostname = tempNewURL.hostname // force the hostname back to [::1]
const client = mqtt.connect(brokerURL, this.brokerConfig)Additional info...
- Calling
mqtt.connect(new URL('http://[::1]:8883'))fails becauseconnectonly accepts astringorurl.parseobject - Calling
mqtt.connect(url.parse('http://[::1]:8883')fails because unlikenew URL,url.parsedrops the square brackets offhostnameandmqtt.js useshostnameto reassemble theurl` - websocket code uses
new URLso whenmqtt.jspasses the reassembled IPhttp://::1:8883it failes with error ERR_INVALID_URL
url.parse vs new URL
url.parse('http://[::1]:8883')
Url {
protocol: 'ws:',
slashes: true,
auth: null,
host: '[::1]:8883',
port: '8883',
hostname: '::1', //<< square brackets are dropped
hash: null,
search: null,
query: null,
pathname: '/',
path: '/',
href: 'ws://[::1]:8883/'
}
new URL('http://[::1]:8883')
URL {
href: 'ws://[::1]:8883/',
origin: 'ws://[::1]:8883',
protocol: 'ws:',
username: '',
password: '',
host: '[::1]:8883',
hostname: '[::1]', //<< square brackets are kept
port: '8883',
pathname: '/',
search: '',
searchParams: URLSearchParams {},
hash: ''
}