node-postgres: Native driver can't connect to UNIX socket with connection string
If you use the native API and specify a UNIX socket in the connectionString
URL, then the actual string passed to the native API incorrectly includes the port, user, and password parameters. This will force postgres to try to connect using a TCP socket, instead of the given UNIX socket.
This is most likely due to an issue in the ConnectionParameters#getLibpqConnectionString
function.
For example, if I specify postgres:///foo
for my connectionString
, then I would expect this string to be passed to the connect
function without alteration. Instead, the connection string ends up as:
user='josh' port='5432' dbname='foo' host=localhost hostaddr=127.0.0.1
About this issue
- Original URL
- State: open
- Created 7 years ago
- Reactions: 4
- Comments: 16 (9 by maintainers)
I think
connectionString
should work the same as if you pass it topsql
directly; e.g. these two CLIs:both connect to database
foo
using unix socket (and peer auth). This is howpg
should work, but it doesn’t work like this on Linux currently unless you set thePGHOST='/var/run/postgresql'
envvar I mentioned above.Peer auth and socket connection should always be used if no hostname is specified. If you specify no hostname but you override username/password you may get an error due to peer auth failure:
If you specify your peer-auth username and absolutely any password (or no password) it still works due to peer auth overriding password:
If you specify a hostname then it should use TCP sockets to connect. I’m not sure if
localhost
should be treated differently, but for me on Linuxpsql
fails to connect:I have a feeling this still used peer auth on Mac, but I don’t have a mac handy to test.
TL;DR: If a hostname is specified, use TCP. If no hostname is specified, use a domain socket.
This affects how peer authentication works when using a connection string. The connection string
postgres:///dbname
or simplydbname
works fine with PostgreSQL on Mac; but when using it on Linux it causes the errors outlined above:To make peer auth work in the same way on Linux as it was previously working on Mac, I set this in my bash profile:
I’m guessing that a fix to this issue would be a breaking change, but maybe we could opt into the new behaviour via a flag in the v7 branch before potentially making it the default behaviour in v8? I’m open to sending a PR, with some guidance.
/tmp
/run/postgresql
How about picking a default between
/run/postgresql
and/tmp
, and if the connection fails because the socket isn’t there, checking the other directory and suggesting it in the error message?It would be the same port, otherwise there wouldn’t be an issue (since the socket file is named based on the port).
listen_addresses
would probably need to be different. This has happened to me, but containers were involved 😃I think
/run/postgresql
already covers the majority of users, but you’re right, there might not be significant downsides to falling back.Now, how do we detect which platforms should use it as a default…? And/or should we also fall back to localhost TCP after all the socket directories have been checked?
That’s certainly a factor, @charmander. I’m glad you’re thinking about these things! I feel like having two different instances of PostgreSQL that not only listen on different ports (i.e. socket names) but also use different temp folders (
/tmp
vs/run/postgresql
) is quite unlikely, as you say, but I can’t really put quantitative values on that unlikeliness. That said, I think auto-detecting for the majority of users beats making everyone learn the intricacies of where libpq puts things; and if you have multiple postgresql versions installed on your machine and they use different locations you’re probably already better equipped to debug this issue since you’re presumably already a very capable user to have gotten into this situation in the first place?I’m definitely open to a PR for this. I’m not sure exactly the fix y’all are looking for after reading the comments. Does it work as expected w/ the pure JS implementation? Fwiw I never use a connection string to connect - always environment variables splatted into an actual config object passed to a pool/client constructor so I haven’t run into this myself.
@charmander Ok, but I spotted differences in behavior of
pg
module andpsql
without args, on Debian… but does not matter,libpq
behaves same way aspsql