From 106a6a83952bfc0e3316d54f99d865e469dcc15a Mon Sep 17 00:00:00 2001 From: Jan Kuehle Date: Thu, 13 Aug 2020 15:50:07 +0100 Subject: [PATCH] Support non-ASCII chars in postgres credentials The `url` crate returns username and password portions of a URL as percent encoded ASCII strings. In order to use them for the Postgres connection, we need to decode them. --- sqlx-core/src/postgres/options/parse.rs | 29 +++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/sqlx-core/src/postgres/options/parse.rs b/sqlx-core/src/postgres/options/parse.rs index e5dd27fd..dce2bad5 100644 --- a/sqlx-core/src/postgres/options/parse.rs +++ b/sqlx-core/src/postgres/options/parse.rs @@ -1,5 +1,6 @@ use crate::error::Error; use crate::postgres::PgConnectOptions; +use percent_encoding::percent_decode_str; use std::str::FromStr; use url::Url; @@ -21,11 +22,19 @@ impl FromStr for PgConnectOptions { let username = url.username(); if !username.is_empty() { - options = options.username(username); + options = options.username( + &*percent_decode_str(username) + .decode_utf8() + .map_err(Error::config)?, + ); } if let Some(password) = url.password() { - options = options.password(password); + options = options.password( + &*percent_decode_str(password) + .decode_utf8() + .map_err(Error::config)?, + ); } let path = url.path().trim_start_matches('/'); @@ -80,3 +89,19 @@ fn it_parses_host_correctly_from_parameter() { assert_eq!(None, opts.socket); assert_eq!("google.database.com", &opts.host); } + +#[test] +fn it_parses_username_with_at_sign_correctly() { + let uri = "postgres://user@hostname:password@hostname:5432/database"; + let opts = PgConnectOptions::from_str(uri).unwrap(); + + assert_eq!("user@hostname", &opts.username); +} + +#[test] +fn it_parses_password_with_non_ascii_chars_correctly() { + let uri = "postgres://username:p@ssw0rd@hostname:5432/database"; + let opts = PgConnectOptions::from_str(uri).unwrap(); + + assert_eq!(Some("p@ssw0rd".into()), opts.password); +}