diff --git a/packages/pg-connection-string/index.js b/packages/pg-connection-string/index.js index 139cc17b1..2c0cf646f 100644 --- a/packages/pg-connection-string/index.js +++ b/packages/pg-connection-string/index.js @@ -18,8 +18,9 @@ function parse(str, options = {}) { let result let dummyHost = false if (/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) { - // Ensure spaces are encoded as %20 - str = encodeURI(str).replace(/%25(\d\d)/g, '%$1') + // Ensure spaces are encoded as %20, and undo the double encoding of + // existing percent-escapes (e.g. %2F, %3a) that encodeURI also produces + str = encodeURI(str).replace(/%25([0-9a-f]{2})/gi, '%$1') } try { diff --git a/packages/pg-connection-string/test/parse.ts b/packages/pg-connection-string/test/parse.ts index 562c3ece0..9cf22e682 100644 --- a/packages/pg-connection-string/test/parse.ts +++ b/packages/pg-connection-string/test/parse.ts @@ -125,6 +125,18 @@ describe('parse', function () { subject.database?.should.equal(' u%20rl') }) + it('keeps percent-encoded characters when the url also contains a space', function () { + const subject = parse('postgres://app:s3cr%2Ft%3A@localhost/db?options=-c search_path=app') + subject.password?.should.equal('s3cr/t:') + subject.options?.should.equal('-c search_path=app') + }) + + it('keeps lowercase percent-encoded characters when the url also contains a stray percent sign', function () { + const subject = parse('postgres://app:s3cr%2bt@localhost/50%off') + subject.password?.should.equal('s3cr+t') + subject.database?.should.equal('50%off') + }) + it('relative url sets database', function () { const relative = 'different_db_on_default_host' const subject = parse(relative)