Lots of URL normalization.

So it doesn't matter if you have a trailing / or not.
diff --git a/openstack/client.go b/openstack/client.go
index 253fcdc..d244053 100644
--- a/openstack/client.go
+++ b/openstack/client.go
@@ -22,6 +22,10 @@
 // This is useful if you wish to explicitly control the version of the identity service that's used for authentication explicitly,
 // for example.
 func NewClient(endpoint string) (*gophercloud.ProviderClient, error) {
+	if !strings.HasSuffix(endpoint, "/") {
+		endpoint = endpoint + "/"
+	}
+
 	return &gophercloud.ProviderClient{IdentityEndpoint: endpoint}, nil
 }
 
@@ -54,10 +58,6 @@
 		return err
 	}
 
-	if !strings.HasSuffix(endpoint, "/") {
-		endpoint = endpoint + "/"
-	}
-
 	switch chosen.ID {
 	case v20:
 		v2Client := NewIdentityV2(client)
@@ -116,19 +116,9 @@
 	}
 
 	// Extract Endpoints from the catalog entries that match the requested Type, Name if provided, and Region if provided.
-	var endpoints = make([]identity2.Endpoint, 0, 6)
+	var endpoints = make([]identity2.Endpoint, 0, 1)
 	for _, entry := range entries {
-		matched := true
-
-		if entry.Type != opts.Type {
-			matched = false
-		}
-
-		if opts.Name != "" && entry.Name != opts.Name {
-			matched = false
-		}
-
-		if matched {
+		if (entry.Type == opts.Type) && (opts.Name == "" || entry.Name == opts.Name) {
 			for _, endpoint := range entry.Endpoints {
 				if opts.Region == "" || endpoint.Region == opts.Region {
 					endpoints = append(endpoints, endpoint)
@@ -243,7 +233,7 @@
 
 // NewIdentityV2 creates a ServiceClient that may be used to interact with the v2 identity service.
 func NewIdentityV2(client *gophercloud.ProviderClient) *gophercloud.ServiceClient {
-	v2Endpoint := client.IdentityEndpoint + "/v2.0/"
+	v2Endpoint := client.IdentityEndpoint + "v2.0/"
 
 	return &gophercloud.ServiceClient{
 		Provider: client,
@@ -253,7 +243,7 @@
 
 // NewIdentityV3 creates a ServiceClient that may be used to access the v3 identity service.
 func NewIdentityV3(client *gophercloud.ProviderClient) *gophercloud.ServiceClient {
-	v3Endpoint := client.IdentityEndpoint + "/v3/"
+	v3Endpoint := client.IdentityEndpoint + "v3/"
 
 	return &gophercloud.ServiceClient{
 		Provider: client,
diff --git a/openstack/utils/choose_version.go b/openstack/utils/choose_version.go
index 57e2a81..402a870 100644
--- a/openstack/utils/choose_version.go
+++ b/openstack/utils/choose_version.go
@@ -75,18 +75,19 @@
 		}
 		return endpoint
 	}
+	normalizedGiven := normalize(identityEndpoint)
 
 	for _, value := range resp.Versions.Values {
 		href := ""
 		for _, link := range value.Links {
 			if link.Rel == "self" {
-				href = link.Href
+				href = normalize(link.Href)
 			}
 		}
 
 		if matching, ok := byID[value.ID]; ok {
 			// Prefer a version that exactly matches the provided endpoint.
-			if normalize(href) == normalize(identityEndpoint) {
+			if href == normalizedGiven {
 				if href == "" {
 					return nil, "", fmt.Errorf("Endpoint missing in version %s response from %s", value.ID, normalized)
 				}
diff --git a/openstack/utils/choose_version_test.go b/openstack/utils/choose_version_test.go
index 4a8a443..b724ee8 100644
--- a/openstack/utils/choose_version_test.go
+++ b/openstack/utils/choose_version_test.go
@@ -53,7 +53,7 @@
 		t.Errorf("Expected %#v to win, but %#v did instead", v3, v)
 	}
 
-	expected := testhelper.Endpoint() + "v3.0"
+	expected := testhelper.Endpoint() + "v3.0/"
 	if endpoint != expected {
 		t.Errorf("Expected endpoint [%s], but was [%s] instead", expected, endpoint)
 	}
@@ -76,7 +76,7 @@
 		t.Errorf("Expected %#v to win, but %#v did instead", v2, v)
 	}
 
-	expected := testhelper.Endpoint() + "v2.0"
+	expected := testhelper.Endpoint() + "v2.0/"
 	if endpoint != expected {
 		t.Errorf("Expected endpoint [%s], but was [%s] instead", expected, endpoint)
 	}