From cdaa715647456601dd1f5ebfb2daa3d7a2828e0c Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Thu, 27 Oct 2022 21:02:19 -0400 Subject: [PATCH 1/6] GODRIVER-2620 Fix hostname parsing for SRV polling. --- .../topology/polling_srv_records_test.go | 2 +- x/mongo/driver/topology/topology.go | 28 +++++++++++++------ 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/x/mongo/driver/topology/polling_srv_records_test.go b/x/mongo/driver/topology/polling_srv_records_test.go index e0e00f2c4e..463f17a56c 100644 --- a/x/mongo/driver/topology/polling_srv_records_test.go +++ b/x/mongo/driver/topology/polling_srv_records_test.go @@ -127,7 +127,7 @@ func compareHosts(t *testing.T, received []description.Server, expected []string func TestPollingSRVRecordsSpec(t *testing.T) { for _, tt := range srvPollingTests { t.Run(tt.name, func(t *testing.T) { - uri := "mongodb+srv://test1.test.build.10gen.cc/?heartbeatFrequencyMS=100" + uri := "mongodb+srv://user:pass@test1.test.build.10gen.cc/?heartbeatFrequencyMS=100" cfg, err := NewConfig(options.Client().ApplyURI(uri), nil) require.NoError(t, err, "error constructing topology configs: %v", err) diff --git a/x/mongo/driver/topology/topology.go b/x/mongo/driver/topology/topology.go index e63e6dd1b9..d4585551bf 100644 --- a/x/mongo/driver/topology/topology.go +++ b/x/mongo/driver/topology/topology.go @@ -14,6 +14,8 @@ import ( "context" "errors" "fmt" + "net" + "net/url" "strings" "sync" "sync/atomic" @@ -234,7 +236,22 @@ func (t *Topology) Connect() error { t.serversLock.Unlock() if t.pollingRequired { - go t.pollSRVRecords() + uri, err := url.Parse(t.cfg.URI) + if err != nil { + return err + } + // sanity check before passing the hostname to resolver + parsedHosts := strings.Split(uri.Host, ",") + if len(parsedHosts) != 1 { + return fmt.Errorf("URI with SRV must include one and only one hostname") + } + _, _, err = net.SplitHostPort(parsedHosts[0]) + if err == nil { + // we were able to successfully extract a port from the host, + // but should not be able to when using SRV + return fmt.Errorf("URI with srv must not include a port number") + } + go t.pollSRVRecords(parsedHosts[0]) t.pollingwg.Add(1) } @@ -556,7 +573,7 @@ func (t *Topology) selectServerFromDescription(desc description.Topology, return suitable, nil } -func (t *Topology) pollSRVRecords() { +func (t *Topology) pollSRVRecords(hosts string) { defer t.pollingwg.Done() serverConfig := newServerConfig(t.cfg.ServerOpts...) @@ -573,13 +590,6 @@ func (t *Topology) pollSRVRecords() { } }() - // remove the scheme - uri := t.cfg.URI[14:] - hosts := uri - if idx := strings.IndexAny(uri, "/?@"); idx != -1 { - hosts = uri[:idx] - } - for { select { case <-pollTicker.C: From 7ad50fe4009d6d11471cb3e6c6023998268f5ece Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Fri, 28 Oct 2022 10:34:20 -0400 Subject: [PATCH 2/6] GODRIVER-2620 Enhance test cases to cover URIs both with and without username/password. --- x/mongo/driver/topology/polling_srv_records_test.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/x/mongo/driver/topology/polling_srv_records_test.go b/x/mongo/driver/topology/polling_srv_records_test.go index 463f17a56c..5f4c2b4ca5 100644 --- a/x/mongo/driver/topology/polling_srv_records_test.go +++ b/x/mongo/driver/topology/polling_srv_records_test.go @@ -125,9 +125,19 @@ func compareHosts(t *testing.T, received []description.Server, expected []string } func TestPollingSRVRecordsSpec(t *testing.T) { + for _, uri := range []string{ + "mongodb+srv://test1.test.build.10gen.cc/?heartbeatFrequencyMS=100", + "mongodb+srv://user:pass@test1.test.build.10gen.cc/?heartbeatFrequencyMS=100", + } { + t.Run(uri, func(t *testing.T) { + testPollingSRVRecordsSpec(t, uri) + }) + } +} + +func testPollingSRVRecordsSpec(t *testing.T, uri string) { for _, tt := range srvPollingTests { t.Run(tt.name, func(t *testing.T) { - uri := "mongodb+srv://user:pass@test1.test.build.10gen.cc/?heartbeatFrequencyMS=100" cfg, err := NewConfig(options.Client().ApplyURI(uri), nil) require.NoError(t, err, "error constructing topology configs: %v", err) From e675205963711d955b65ea71ca5f00a3d5108c6c Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Fri, 28 Oct 2022 14:27:11 -0400 Subject: [PATCH 3/6] GODRIVER-2620 Minor polish. --- x/mongo/driver/topology/topology.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/x/mongo/driver/topology/topology.go b/x/mongo/driver/topology/topology.go index d4585551bf..eb0ac425a1 100644 --- a/x/mongo/driver/topology/topology.go +++ b/x/mongo/driver/topology/topology.go @@ -241,17 +241,16 @@ func (t *Topology) Connect() error { return err } // sanity check before passing the hostname to resolver - parsedHosts := strings.Split(uri.Host, ",") - if len(parsedHosts) != 1 { + if parsedHosts := strings.Split(uri.Host, ","); len(parsedHosts) != 1 { return fmt.Errorf("URI with SRV must include one and only one hostname") } - _, _, err = net.SplitHostPort(parsedHosts[0]) + _, _, err = net.SplitHostPort(uri.Host) if err == nil { // we were able to successfully extract a port from the host, // but should not be able to when using SRV return fmt.Errorf("URI with srv must not include a port number") } - go t.pollSRVRecords(parsedHosts[0]) + go t.pollSRVRecords(uri.Host) t.pollingwg.Add(1) } From 5b180caa84a0e6425578489510df27c619d96533 Mon Sep 17 00:00:00 2001 From: Qingyang Hu <103950869+qingyang-hu@users.noreply.github.com> Date: Fri, 28 Oct 2022 14:28:39 -0400 Subject: [PATCH 4/6] Label test helper. Co-authored-by: Preston Vasquez <24281431+prestonvasquez@users.noreply.github.com> --- x/mongo/driver/topology/polling_srv_records_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/mongo/driver/topology/polling_srv_records_test.go b/x/mongo/driver/topology/polling_srv_records_test.go index 5f4c2b4ca5..d9d000eb21 100644 --- a/x/mongo/driver/topology/polling_srv_records_test.go +++ b/x/mongo/driver/topology/polling_srv_records_test.go @@ -136,6 +136,7 @@ func TestPollingSRVRecordsSpec(t *testing.T) { } func testPollingSRVRecordsSpec(t *testing.T, uri string) { + t.Helper() for _, tt := range srvPollingTests { t.Run(tt.name, func(t *testing.T) { cfg, err := NewConfig(options.Client().ApplyURI(uri), nil) From 19a4154821658a2571ebede4e0a9e50f6dcfea90 Mon Sep 17 00:00:00 2001 From: Qingyang Hu <103950869+qingyang-hu@users.noreply.github.com> Date: Fri, 28 Oct 2022 14:33:20 -0400 Subject: [PATCH 5/6] Comment non-specification-required test. Co-authored-by: Kevin Albertson --- x/mongo/driver/topology/polling_srv_records_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/mongo/driver/topology/polling_srv_records_test.go b/x/mongo/driver/topology/polling_srv_records_test.go index d9d000eb21..05b4e46723 100644 --- a/x/mongo/driver/topology/polling_srv_records_test.go +++ b/x/mongo/driver/topology/polling_srv_records_test.go @@ -127,6 +127,7 @@ func compareHosts(t *testing.T, received []description.Server, expected []string func TestPollingSRVRecordsSpec(t *testing.T) { for _, uri := range []string{ "mongodb+srv://test1.test.build.10gen.cc/?heartbeatFrequencyMS=100", + // Test with user:pass as a regression test for GODRIVER-2620 "mongodb+srv://user:pass@test1.test.build.10gen.cc/?heartbeatFrequencyMS=100", } { t.Run(uri, func(t *testing.T) { From eae97a78e25fe3ef6b0c722d678a3829b924be96 Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Fri, 28 Oct 2022 14:38:49 -0400 Subject: [PATCH 6/6] Indent code --- x/mongo/driver/topology/polling_srv_records_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x/mongo/driver/topology/polling_srv_records_test.go b/x/mongo/driver/topology/polling_srv_records_test.go index 05b4e46723..c1811aaeae 100644 --- a/x/mongo/driver/topology/polling_srv_records_test.go +++ b/x/mongo/driver/topology/polling_srv_records_test.go @@ -127,7 +127,7 @@ func compareHosts(t *testing.T, received []description.Server, expected []string func TestPollingSRVRecordsSpec(t *testing.T) { for _, uri := range []string{ "mongodb+srv://test1.test.build.10gen.cc/?heartbeatFrequencyMS=100", - // Test with user:pass as a regression test for GODRIVER-2620 + // Test with user:pass as a regression test for GODRIVER-2620 "mongodb+srv://user:pass@test1.test.build.10gen.cc/?heartbeatFrequencyMS=100", } { t.Run(uri, func(t *testing.T) { @@ -137,7 +137,7 @@ func TestPollingSRVRecordsSpec(t *testing.T) { } func testPollingSRVRecordsSpec(t *testing.T, uri string) { - t.Helper() + t.Helper() for _, tt := range srvPollingTests { t.Run(tt.name, func(t *testing.T) { cfg, err := NewConfig(options.Client().ApplyURI(uri), nil)