Skip to content

Commit

Permalink
GODRIVER-2620 Fix hostname parsing for SRV polling. (#1112)
Browse files Browse the repository at this point in the history
* GODRIVER-2620 Fix hostname parsing for SRV polling.

Co-authored-by: Preston Vasquez <[email protected]>
Co-authored-by: Kevin Albertson <[email protected]>
  • Loading branch information
3 people committed Nov 1, 2022
1 parent 5762c6a commit 861364b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
15 changes: 14 additions & 1 deletion x/mongo/driver/topology/polling_srv_records_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,22 @@ 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:[email protected]/?heartbeatFrequencyMS=100",
} {
t.Run(uri, func(t *testing.T) {
testPollingSRVRecordsSpec(t, uri)
})
}
}

func testPollingSRVRecordsSpec(t *testing.T, uri string) {
t.Helper()
for _, tt := range srvPollingTests {
t.Run(tt.name, func(t *testing.T) {
cs, err := connstring.ParseAndValidate("mongodb+srv://test1.test.build.10gen.cc/?heartbeatFrequencyMS=100")
cs, err := connstring.ParseAndValidate(uri)
require.NoError(t, err, "Problem parsing the uri: %v", err)
topo, err := New(
WithConnString(func(connstring.ConnString) connstring.ConnString { return cs }),
Expand Down
27 changes: 18 additions & 9 deletions x/mongo/driver/topology/topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"context"
"errors"
"fmt"
"net"
"net/url"
"strings"
"sync"
"sync/atomic"
Expand Down Expand Up @@ -230,7 +232,21 @@ 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
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(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(uri.Host)
t.pollingwg.Add(1)
}

Expand Down Expand Up @@ -552,7 +568,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...)
Expand All @@ -569,13 +585,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:
Expand Down

0 comments on commit 861364b

Please sign in to comment.