From 4bb3fa253ee79741419d4a043d398fd98637c64e Mon Sep 17 00:00:00 2001 From: Joel Nordell <94570446+joel-u410@users.noreply.github.com> Date: Fri, 23 Feb 2024 10:05:12 -0600 Subject: [PATCH] Reformat the postgres connection URL to work properly with unix socket connections (#150) I ran into a problem trying to connect `namadexer` to a postgres database using a Unix domain socket rather than a network hostname. This is necessary in order to run the `server` in environments like Google Cloud Run, which exposes connections to Postgresql as a local domain socket. **The problem:** * Google Cloud SQL creates a socket with a path like `/cloudsql/namada:us-central1:namadexer-db-instance` * Setting `DATABASE_HOST=/cloudsql/namada:us-central1:namadexer-db-instance` would produce a connection URL like the following: ``` postgres://postgres:wow@/cloudsql/namada:my-region:namadexer-db-instance:5432/blockchain ``` * This URL is not valid. **The solution:** * There is an alternate form for the postgres URL, like this: ``` postgres://postgres:wow@dummy-hostname:5432/blockchain?host=/cloudsql/namada:my-region:namadexer-db-instance ``` * In this case, the actual `host` can contain `/` and `:` characters just fine. * The `dummy-hostname` in the host part of the URL must be present for the URL to be parsed properly, but is ignored. --- src/database.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/database.rs b/src/database.rs index 33b5f9a..7d2c292 100644 --- a/src/database.rs +++ b/src/database.rs @@ -67,14 +67,25 @@ impl Database { // sqlx expects config of the form: // postgres://user:password@host:port/db_name let config = format!( - "postgres://{}:{}@{}:{}/{}", - db_config.user, db_config.password, db_config.host, db_config.port, db_config.dbname + // In order to accommodate the use of a unix socket, we are actually supplying a dummy + // string "not-the-host" to the host portion of the URL, and putting the actual host in the + // query string. This is the only way to provide a "host" to sqlx that contains slashes. + // When "host=" is given as a query parameter, postgres ignores the host portion of the URL + // though it is still required to be present for the URL to parse correctly. + "postgres://{}:{}@not-the-host:{}/{}?host={}", + db_config.user, db_config.password, db_config.port, db_config.dbname, db_config.host ); // If timeout setting is not present in the provided configuration, // lets use our default timeout. let timeout = db_config.connection_timeout.unwrap_or(DATABASE_TIMEOUT); + debug!( + "connecting to database at {} with timeout {}", + config.replace(&db_config.password, "*****"), + timeout + ); + let pool = PgPoolOptions::new() .max_connections(10) .acquire_timeout(Duration::from_secs(timeout))