Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Go url.Parse(string) fails with certain user names or passwords

Tags:

url

go

build

Using a URL that has worked in the past, I know receive a parsing error from net/url. What's wrong with it?

parse postgres://user:abc{[email protected]:5432/db?sslmode=require: net/url: invalid userinfo

Sample application

See https://play.golang.com/p/mQZaN5JN3_q to run.

package main

import (
    "fmt"
    "net/url"
)

func main() {
    dsn := "postgres://user:abc{[email protected]:5432/db?sslmode=require"

    u, err := url.Parse(dsn)
    fmt.Println(u, err)
}
like image 639
klotz Avatar asked Feb 07 '18 19:02

klotz


3 Answers

Use url.UserPassword func :

package main

import (
    "fmt"
    "net/url"
)

func main() {
    dsn := "postgres://example.com:5432/db?sslmode=require" 

    u, err := url.Parse(dsn)
    if err != nil {
         fmt.Printf("ERROR: %v\n", err)
         return
    }
    u.User = url.UserPassword("user", "abc{DEf1=ghi")
    fmt.Println("url:\t", u)

}
like image 53
Adrien Parrochia Avatar answered Sep 20 '22 17:09

Adrien Parrochia


It turns out up until Go v1.9.3 net/url didn't validate the user info when parsing a url. This may break existing applications when compiled using v1.9.4 if the username or password contain special characters.

It now expects the user info to be percent encoded string in order to handle special characters. The new behaviour got introduced in ba1018b.

Fixed sample application

package main

import (
    "fmt"
    "net/url"
)

func main() {
    dsn1 := "postgres://user:abc{[email protected]:5432/db?sslmode=require" // this works up until 1.9.3 but no longer in 1.9.4
    dsn2 := "postgres://user:abc%[email protected]:5432/db?sslmode=require" // this works everywhere, note { is now %7B

    u, err := url.Parse(dsn1)
    fmt.Println("1st url:\t", u, err)

    u, err = url.Parse(dsn2)
    fmt.Println("2nd url:\t", u, err)
}

Run the code on https://play.golang.com/p/jGIQgbiKZwz.

like image 30
klotz Avatar answered Sep 19 '22 17:09

klotz


Well, you can just

url.QueryEscape("your#$%^&*(proper$#$%%^(password")

and use this one to parse your url.

like image 34
Grrrben Avatar answered Sep 18 '22 17:09

Grrrben