Ejemplo n.º 1
0
func ParseURL(mod mb.Module, rawURL string) (mb.HostData, error) {
	c := struct {
		Username string `config:"username"`
		Password string `config:"password"`
	}{}
	if err := mod.UnpackConfig(&c); err != nil {
		return mb.HostData{}, err
	}

	if parts := strings.SplitN(rawURL, "://", 2); len(parts) != 2 {
		// Add scheme.
		rawURL = fmt.Sprintf("postgres://%s", rawURL)
	}

	u, err := url.Parse(rawURL)
	if err != nil {
		return mb.HostData{}, fmt.Errorf("error parsing URL: %v", err)
	}

	parse.SetURLUser(u, c.Username, c.Password)

	if timeout := mod.Config().Timeout; timeout > 0 {
		q := u.Query()
		q.Set("connect_timeout", strconv.Itoa(int(timeout.Seconds())))
		u.RawQuery = q.Encode()
	}

	// https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
	connString, err := pq.ParseURL(u.String())
	if err != nil {
		return mb.HostData{}, err
	}

	h := parse.NewHostDataFromURL(u)

	// Store the connection string instead of URL to avoid the cost of sql.Open
	// parsing the URL on each call.
	h.URI = connString

	// Postgres URLs can use a host query param to specify the host. This is
	// used for unix domain sockets (postgres:///dbname?host=/var/lib/postgres).
	if host := u.Query().Get("host"); u.Host == "" && host != "" {
		h.Host = host
	}

	return h, nil
}
Ejemplo n.º 2
0
// ParseDSN creates a DSN (data source name) string by parsing the host.
// It validates the resulting DSN and returns an error if the DSN is invalid.
//
//   Format:  [username[:password]@][protocol[(address)]]/
//   Example: root:test@tcp(127.0.0.1:3306)/
func ParseDSN(mod mb.Module, host string) (mb.HostData, error) {
	c := struct {
		Username string `config:"username"`
		Password string `config:"password"`
	}{}
	if err := mod.UnpackConfig(&c); err != nil {
		return mb.HostData{}, err
	}

	config, err := mysql.ParseDSN(host)
	if err != nil {
		return mb.HostData{}, errors.Wrapf(err, "error parsing mysql host")
	}

	if config.User == "" {
		config.User = c.Username
	}

	if config.Passwd == "" {
		config.Passwd = c.Password
	}

	// Add connection timeouts to the DSN.
	if timeout := mod.Config().Timeout; timeout > 0 {
		config.Timeout = timeout
		config.ReadTimeout = timeout
		config.WriteTimeout = timeout
	}

	noCredentialsConfig := *config
	noCredentialsConfig.User = ""
	noCredentialsConfig.Passwd = ""

	return mb.HostData{
		URI:          config.FormatDSN(),
		SanitizedURI: noCredentialsConfig.FormatDSN(),
		Host:         config.Addr,
		User:         config.User,
		Password:     config.Passwd,
	}, nil
}