Skip to content

Commit 3c3b168

Browse files
committed
refactor: Use new URL for connection string parsing
This commit refactors the connection URL parsing logic in `src/index.js` to use the `new URL()` constructor. This change provides a more robust and standardized way to parse connection strings, addressing several limitations of the previous implementation: - **IPv6 Support:** The new parsing logic correctly handles IPv6 addresses in connection strings. - **Encoded Password Handling:** Usernames and passwords with special characters that have been URL-encoded are now correctly decoded. To achieve this, the `parseUrl` function was rewritten to replace the `postgres://` or `postgresql://` protocol with `http://` before passing the string to the `URL` constructor. This allows the use of the standard URL parsing mechanism for a custom protocol. Additionally, two new helper functions, `parseHost` and `parsePort`, have been introduced to correctly extract host and port information from various formats, including single-host, multi-host, and IPv6 addresses.
1 parent 32feb25 commit 3c3b168

File tree

1 file changed

+35
-17
lines changed

1 file changed

+35
-17
lines changed

src/index.js

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -462,9 +462,9 @@ function parseOptions(a, b) {
462462
}
463463

464464
return {
465-
host : Array.isArray(host) ? host : host.split(',').map(x => x.split(':')[0]),
466-
port : Array.isArray(port) ? port : host.split(',').map(x => parseInt(x.split(':')[1] || port)),
467-
path : o.path || host.indexOf('/') > -1 && host + '/.s.PGSQL.' + port,
465+
host : Array.isArray(host) ? host : host.split(',').map(x => parseHost(x)),
466+
port : Array.isArray(port) ? port : host.split(',').map(x => parsePort(x, port)),
467+
path : o.path || (host.indexOf('/') > -1 && host + '/.s.PGSQL.' + port),
468468
database : o.database || o.db || (url.pathname || '').slice(1) || env.PGDATABASE || user,
469469
user : user,
470470
pass : o.pass || o.password || url.password || env.PGPASSWORD || '',
@@ -533,27 +533,25 @@ function parseTransform(x) {
533533
}
534534
}
535535

536-
function parseUrl(url) {
537-
if (!url || typeof url !== 'string')
536+
function parseUrl(x) {
537+
if (!x || typeof x !== 'string')
538538
return { url: { searchParams: new Map() } }
539539

540-
let host = url
541-
host = host.slice(host.indexOf('://') + 3).split(/[?/]/)[0]
542-
host = decodeURIComponent(host.slice(host.indexOf('@') + 1))
540+
const url = new URL(x.replace(/^postgres(ql)?:/, 'http:'))
543541

544-
const urlObj = new URL(url.replace(host, host.split(',')[0]))
542+
const multihost = url.hostname.includes(',') && decodeURIComponent(url.hostname)
545543

546544
return {
547545
url: {
548-
username: decodeURIComponent(urlObj.username),
549-
password: decodeURIComponent(urlObj.password),
550-
host: urlObj.host,
551-
hostname: urlObj.hostname,
552-
port: urlObj.port,
553-
pathname: urlObj.pathname,
554-
searchParams: urlObj.searchParams
546+
username: decodeURIComponent(url.username),
547+
password: decodeURIComponent(url.password),
548+
host: url.host,
549+
hostname: multihost ? multihost.split(',')[0] : url.hostname,
550+
port: url.port,
551+
pathname: url.pathname,
552+
searchParams: url.searchParams
555553
},
556-
multihost: host.indexOf(',') > -1 && host
554+
multihost: multihost
557555
}
558556
}
559557

@@ -564,3 +562,23 @@ function osUsername() {
564562
return process.env.USERNAME || process.env.USER || process.env.LOGNAME // eslint-disable-line
565563
}
566564
}
565+
566+
function parseHost(host) {
567+
if (host.charAt(0) === '[')
568+
return host.slice(1, -1)
569+
570+
if (host.includes(':') && host.split(':').length > 2)
571+
return ''
572+
573+
return host.split(':')[0]
574+
}
575+
576+
function parsePort(host, port) {
577+
if (host.charAt(0) === '[' && host.includes(']:'))
578+
return parseInt(host.split(']:')[1])
579+
580+
if (host.includes(':') && host.split(':').length === 2)
581+
return parseInt(host.split(':')[1])
582+
583+
return parseInt(port)
584+
}

0 commit comments

Comments
 (0)