fix: preserve multi-host HA DSN addresses (Go 1.26) - #1946
fix: preserve multi-host HA DSN addresses (Go 1.26)#1946sankalpsthakur wants to merge 2 commits into
Conversation
Extract HA host lists from the raw DSN authority instead of only splitting url.Host, so multi-host DSNs (including bracketed IPv6) are not collapsed by URL host normalization. Add ParseDSN and churl regression tests for the issue 1784 multi-host cases.
| }, | ||
| "", | ||
| }, | ||
| // Regression for https://github.com/ClickHouse/clickhouse-go/issues/1784 |
There was a problem hiding this comment.
we do not name tests after issues - tests should match functionality
please remove.
| // (Go 1.26 net/url multi-host / HA DSN). Also covers auth + query. | ||
| { | ||
| "HA multi-host with auth and secure (issue 1784)", | ||
| "clickhouse://user:pass@host1:9440,host2:9440/database?secure=true", |
There was a problem hiding this comment.
what user and password would be used for second host?
what if credentials are overridden in options?
There should be tests for all this cases.
|
|
||
| // addrListFromDSN extracts host[:port] entries from the DSN authority. | ||
| // Supports comma-separated HA hosts and bracketed IPv6 literals. | ||
| func addrListFromDSN(raw string) []string { |
There was a problem hiding this comment.
There are already tools that can parse such form of url:
package main
import (
"fmt"
"net"
"net/url"
"strings"
)
type TargetHost struct {
Host string
Port string
}
func main() {
rawURL := "clickhouse://user:pass@host1:9440,host2:9440/database?secure=true"
// 1. Parse into a standard URL structure
u, err := url.Parse(rawURL)
if err != nil {
panic(err)
}
// 2. Extract Username
username := ""
if u.User != nil {
username = u.User.Username()
}
// 3. Extract the complete host cluster string
// u.Host will contain "host1:9440,host2:9440"
clusterStr := u.Host
// 4. Split the individual hosts by comma
hostTokens := strings.Split(clusterStr, ",")
var hosts []TargetHost
for _, token := range hostTokens {
h, p, err := net.SplitHostPort(token)
if err != nil {
// Fallback if port is missing from a specific host token
h = token
p = ""
}
hosts = append(hosts, TargetHost{Host: h, Port: p})
}
// Output results
fmt.Println("Username:", username)
fmt.Println("Database:", strings.TrimPrefix(u.Path, "/"))
fmt.Println("Hosts found:")
for i, h := range hosts {
fmt.Printf(" [%d] Host: %s, Port: %s\n", i, h.Host, h.Port)
}
}
chernser
left a comment
There was a problem hiding this comment.
- correct implementation - use std lib
- documentation how it works and changelog
- more tests with authentication
- ideally integration test
- Use stdlib net.SplitHostPort/net.JoinHostPort in splitHostList for per-host validation/normalization; document HA handling and Go 1.26 net/url tightening (churl as Go 1.25.7 copy plus raw-authority extraction). Clarify single cluster-wide Auth and query override. - Add CHANGELOG Unreleased entry describing fix. - Expand ParseDSN tests: rename from issue-number style to functional names, add multi-host cases for auth overridden via query, auth via query only, encoded passwords, IPv6 with auth, and 3-host preservation. - Expand host-list helper tests: rename, add auth-override case and additional splitHostList coverage. Fixes ClickHouse#1784
|
Thanks @chernser, addressed the feedback in the latest push. Documented lib/churl and refactored splitHostList to use net.SplitHostPort and JoinHostPort, expanded docs and added a changelog entry. Added more auth tests for multi-host cases including query overrides and IPv6. Unit tests pass. Let me know if you want integration coverage as well. |
Summary
Hardens multi-host (HA) DSN address parsing so host lists stay intact across
net/urlhost-normalization differences (including Go 1.26-era multi-host / HA DSN breakage reported in #1784).fromDSNalready useschurl.Parse(from #1787). This change additionally extracts the HA host list from the raw DSN authority instead of onlystrings.Split(dsn.Host, ","), so:host1:9440,host2:9440)[::1]:9440,[2001:db8::1]:9440) instead of collapsing to the last hostChanges
dsnAddrList/addrListFromDSN/splitHostListinclickhouse_options.golib/churlmulti-host parse testsFixes #1784
Checklist
Validation
Results (Go 1.26.0):
AI/LLM disclosure