diff --git a/fclient/client.go b/fclient/client.go index 7ec72477..2efde726 100644 --- a/fclient/client.go +++ b/fclient/client.go @@ -346,7 +346,7 @@ retryResolution: // If the cache returned nothing then we'll have no results here, // so go and hit the network. if len(resolutionResults) == 0 { - resolutionResults, err = ResolveServer(r.Context(), serverName) + resolutionResults, err = ResolveServer(r.Context(), &NewClient(WithTransport(f.getTransport(string(serverName), f.dialer))).client, serverName) if err != nil { return nil, err } diff --git a/fclient/resolve.go b/fclient/resolve.go index 66c0c8cf..a152541a 100644 --- a/fclient/resolve.go +++ b/fclient/resolve.go @@ -19,6 +19,7 @@ import ( "context" "fmt" "net" + "net/http" "strconv" "github.com/matrix-org/gomatrixserverlib/spec" @@ -37,14 +38,14 @@ type ResolutionResult struct { // Returns a slice of ResolutionResult that can be used to send a federation // request to the server using a given server name. // Returns an error if the server name isn't valid. -func ResolveServer(ctx context.Context, serverName spec.ServerName) (results []ResolutionResult, err error) { - return resolveServer(ctx, serverName, true) +func ResolveServer(ctx context.Context, client *http.Client, serverName spec.ServerName) (results []ResolutionResult, err error) { + return resolveServer(ctx, client, serverName, true) } // resolveServer does the same thing as ResolveServer, except it also requires // the checkWellKnown parameter, which indicates whether a .well-known file // should be looked up. -func resolveServer(ctx context.Context, serverName spec.ServerName, checkWellKnown bool) (results []ResolutionResult, err error) { +func resolveServer(ctx context.Context, client *http.Client, serverName spec.ServerName, checkWellKnown bool) (results []ResolutionResult, err error) { host, port, valid := spec.ParseAndValidateServerName(serverName) if !valid { err = fmt.Errorf("Invalid server name") @@ -94,10 +95,10 @@ func resolveServer(ctx context.Context, serverName spec.ServerName, checkWellKno if checkWellKnown { // 3. If the hostname is not an IP literal var result *WellKnownResult - result, err = LookupWellKnown(ctx, serverName) + result, err = LookupWellKnown(ctx, client, serverName) if err == nil { // We don't want to check .well-known on the result - return resolveServer(ctx, result.NewAddress, false) + return resolveServer(ctx, client, result.NewAddress, false) } } diff --git a/fclient/resolve_test.go b/fclient/resolve_test.go index 6036cdf4..89a2953a 100644 --- a/fclient/resolve_test.go +++ b/fclient/resolve_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net" + "net/http" "reflect" "testing" @@ -27,8 +28,8 @@ func assertCritical(t *testing.T, val, expected interface{}) { // and expected certificate name. // If one of them doesn't match, or the resolution function returned with an // error, it aborts the current test. -func testResolve(t *testing.T, serverName spec.ServerName, destination, host, certName string) { - res, err := ResolveServer(context.Background(), serverName) +func testResolve(t *testing.T, client *http.Client, serverName spec.ServerName, destination, host, certName string) { + res, err := ResolveServer(context.Background(), client, serverName) assertCritical(t, err, nil) assertCritical(t, len(res), 1) assertCritical(t, res[0].Destination, destination) @@ -40,6 +41,7 @@ func testResolve(t *testing.T, serverName spec.ServerName, destination, host, ce func TestResolutionIPLiteral(t *testing.T) { testResolve( t, + http.DefaultClient, spec.ServerName("42.42.42.42"), // The server name is an IP literal without a port "42.42.42.42:8448", // Destination must be the IP address + port 8448 "42.42.42.42", // Host must be the IP address @@ -51,6 +53,7 @@ func TestResolutionIPLiteral(t *testing.T) { func TestResolutionIPv6Literal(t *testing.T) { testResolve( t, + http.DefaultClient, spec.ServerName("[42:42::42]"), // The server name is an IP literal without a port "[42:42::42]:8448", // Destination must be the IP address + port 8448 "[42:42::42]", // Host must be the IP address @@ -62,6 +65,7 @@ func TestResolutionIPv6Literal(t *testing.T) { func TestResolutionIPLiteralWithPort(t *testing.T) { testResolve( t, + http.DefaultClient, spec.ServerName("42.42.42.42:443"), // The server name is an IP literal with a port "42.42.42.42:443", // Destination must be the IP address + port "42.42.42.42:443", // Host must be the IP address + port @@ -73,6 +77,7 @@ func TestResolutionIPLiteralWithPort(t *testing.T) { func TestResolutionIPv6LiteralWithPort(t *testing.T) { testResolve( t, + http.DefaultClient, spec.ServerName("[42:42::42]:443"), // The server name is an IP literal with a port "[42:42::42]:443", // Destination must be the IP address + port "[42:42::42]:443", // Host must be the IP address + port @@ -84,6 +89,7 @@ func TestResolutionIPv6LiteralWithPort(t *testing.T) { func TestResolutionHostnameAndPort(t *testing.T) { testResolve( t, + http.DefaultClient, spec.ServerName("example.com:4242"), // The server name is not an IP literal and includes an explicit port "example.com:4242", // Destination must be the hostname + port "example.com:4242", // Host must be the hostname + port @@ -102,6 +108,7 @@ func TestResolutionHostnameWellKnownWithIPLiteral(t *testing.T) { testResolve( t, + http.DefaultClient, spec.ServerName("example.com"), // The server name is a domain hosting a .well-known file which specifies an IP literal without a port "42.42.42.42:8448", // Destination must be the IP literal + port 8448 "42.42.42.42", // Host must be the IP literal @@ -120,6 +127,7 @@ func TestResolutionHostnameWellKnownWithIPLiteralAndPort(t *testing.T) { testResolve( t, + http.DefaultClient, spec.ServerName("example.com"), // The server name is a domain hosting a .well-known file which specifies an IP literal with a port "42.42.42.42:443", // Destination must be the IP literal + port "42.42.42.42:443", // Host must be the IP literal + port @@ -138,6 +146,7 @@ func TestResolutionHostnameWellKnownWithHostnameAndPort(t *testing.T) { testResolve( t, + http.DefaultClient, spec.ServerName("example.com"), // The server name is a domain hosting a .well-known file which specifies a hostname that's not an IP literal and has a port "matrix.example.com:4242", // Destination must be the hostname + port "matrix.example.com:4242", // Host must be the hostname + port @@ -159,6 +168,7 @@ func TestResolutionHostnameWellKnownWithHostnameSRV(t *testing.T) { testResolve( t, + http.DefaultClient, spec.ServerName("example.com"), // The server name is a domain hosting a .well-known file which specifies a hostname that's not an IP literal, has no port and for which a SRV record with a non-0 exists "matrix.otherexample.com:4242", // Destination must be the hostname + port from the SRV record "matrix.example.com", // Host must be the delegated hostname @@ -180,6 +190,7 @@ func TestResolutionHostnameWellKnownWithHostnameNoSRV(t *testing.T) { testResolve( t, + http.DefaultClient, spec.ServerName("example.com"), // The server name is a domain hosting a .well-known file which specifies a hostname that's not an IP literal, has no port and for which no SRV record exists "matrix.example.com:8448", // Destination must be the delegated hostname + port 8448 "matrix.example.com", // Host must be the delegated hostname @@ -194,6 +205,7 @@ func TestResolutionHostnameWithSRV(t *testing.T) { testResolve( t, + http.DefaultClient, spec.ServerName("example.com"), // The server name is a domain for which a SRV record exists with a non-0 port "matrix.otherexample.com:4242", // Destination must be the hostname + port "example.com", // Host must be the server name @@ -214,6 +226,7 @@ func TestResolutionHostnameWithNoWellKnownNorSRV(t *testing.T) { testResolve( t, + http.DefaultClient, spec.ServerName("example.com"), // The server name is a domain for no .well-known file nor SRV record exist "example.com:8448", // Destination must be the hostname + 8448 "example.com", // Host must be the server name diff --git a/fclient/well_known.go b/fclient/well_known.go index 102850a9..b46f9158 100644 --- a/fclient/well_known.go +++ b/fclient/well_known.go @@ -29,7 +29,7 @@ type WellKnownResult struct { // LookupWellKnown looks up a well-known record for a matrix server. If one if // found, it returns the server to redirect to. -func LookupWellKnown(ctx context.Context, serverNameType spec.ServerName) (*WellKnownResult, error) { +func LookupWellKnown(ctx context.Context, client *http.Client, serverNameType spec.ServerName) (*WellKnownResult, error) { serverName := string(serverNameType) // Handle ending "/" @@ -43,7 +43,6 @@ func LookupWellKnown(ctx context.Context, serverNameType spec.ServerName) (*Well return nil, err } // Given well-known should be quite small and fast to fetch, timeout the request after 30s. - client := http.Client{Timeout: time.Second * 30} resp, err := client.Do(req) if err != nil { return nil, err