@@ -207,24 +207,73 @@ func (cfg *Config) makeDefaultConfigValue() {
207207 }
208208}
209209
210+ func needEscape (s string ) bool {
211+ unescaped , err := url .QueryUnescape (s )
212+ if err != nil {
213+ return true
214+ }
215+ return url .QueryEscape (unescaped ) != s
216+ }
217+
218+ func autoEncodeUserPassInDSN (dsn string ) (string , error ) {
219+ i := strings .Index (dsn , "://" )
220+ if i == - 1 {
221+ return dsn , nil
222+ }
223+ rest := dsn [i + 3 :]
224+ atIdx := strings .Index (rest , "@" )
225+ if atIdx == - 1 {
226+ return dsn , nil
227+ }
228+ userinfo := rest [:atIdx ]
229+ user := userinfo
230+ pass := ""
231+ if idx := strings .Index (userinfo , ":" ); idx != - 1 {
232+ user = userinfo [:idx ]
233+ pass = userinfo [idx + 1 :]
234+ }
235+ var encUser , encPass string
236+ if needEscape (user ) {
237+ encUser = url .QueryEscape (user )
238+ } else {
239+ encUser = user
240+ }
241+ if needEscape (pass ) {
242+ encPass = url .QueryEscape (pass )
243+ } else {
244+ encPass = pass
245+ }
246+ var encUserinfo string
247+ if pass != "" {
248+ encUserinfo = encUser + ":" + encPass
249+ } else {
250+ encUserinfo = encUser
251+ }
252+ encodedDSN := dsn [:i + 3 ] + encUserinfo + rest [atIdx :]
253+ return encodedDSN , nil
254+ }
255+
210256// ParseDSN parses the DSN string to a Config
211257func ParseDSN (dsn string ) (* Config , error ) {
212- u , err := url . Parse (dsn )
258+ encodedDSN , err := autoEncodeUserPassInDSN (dsn )
213259 if err != nil {
214260 return nil , err
215261 }
262+ u , err := url .Parse (encodedDSN )
263+ if err != nil {
264+ logger .Error ("ParseDSN" , "err" , err )
265+ return nil , err
266+ }
216267 cfg := NewConfig ()
217268
218269 if strings .HasSuffix (u .Scheme , "http" ) {
219270 cfg .SSLMode = SSL_MODE_DISABLE
220271 }
221272
222273 if len (u .Path ) > 1 {
223- // skip '/'
224274 cfg .Database = u .Path [1 :]
225275 }
226276 if u .User != nil {
227- // it is expected that empty password will be dropped out on Parse and Format
228277 cfg .User = u .User .Username ()
229278 if passwd , ok := u .User .Password (); ok {
230279 cfg .Password = passwd
@@ -253,10 +302,8 @@ func ParseDSN(dsn string) (*Config, error) {
253302 cfg .Host = net .JoinHostPort (u .Host , "443" )
254303 }
255304 }
256-
257305 return cfg , nil
258306}
259-
260307func (cfg * Config ) Connect (ctx context.Context ) (driver.Conn , error ) {
261308 return DatabendDriver {}.OpenWithConfig (ctx , cfg )
262309}
0 commit comments