From 7d8262307cb40c1f21fd79fe52cdfd36a7dcb5cd Mon Sep 17 00:00:00 2001
From: Ross Jones <ross@mailbolt.com>
Date: Mon, 15 May 2023 17:18:51 +0100
Subject: [PATCH] fix: use https URI when multiaddress specifies tls (#177)

Currently any clients created through `NewApiWithClient` will make a
HTTP request to the api, even if the multiaddress specifies TLS or (the
deprecated multiaddr option) https.

This commit addresses this by having NewApiWithClient iterate the
available protocols for the multiaddress, specifying the URL proto as
https if it finds TLS or HTTPS is specified. The default continues to be
http for those multiaddresses that do not specify these options.

Should resolve #176

This commit was moved from ipfs/go-ipfs-http-client@7e1de1f7ccfa8cd1f616e94664886fe04d70806e
---
 client/httpapi/api.go      | 16 +++++++++++++++-
 client/httpapi/api_test.go | 28 ++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/client/httpapi/api.go b/client/httpapi/api.go
index b7cfb2b52..5584de85d 100644
--- a/client/httpapi/api.go
+++ b/client/httpapi/api.go
@@ -107,7 +107,21 @@ func NewApiWithClient(a ma.Multiaddr, c *http.Client) (*HttpApi, error) {
 		}
 	}
 
-	return NewURLApiWithClient(url, c)
+	proto := "http://"
+
+	// By default, DialArgs is going to provide details suitable for connecting
+	// a socket to, but not really suitable for making an informed choice of http
+	// protocol.  For multiaddresses specifying tls and/or https we want to make
+	// a https request instead of a http request.
+	protocols := a.Protocols()
+	for _, p := range protocols {
+		if p.Code == ma.P_HTTPS || p.Code == ma.P_TLS {
+			proto = "https://"
+			break
+		}
+	}
+
+	return NewURLApiWithClient(proto+url, c)
 }
 
 func NewURLApiWithClient(url string, c *http.Client) (*HttpApi, error) {
diff --git a/client/httpapi/api_test.go b/client/httpapi/api_test.go
index 2832d722d..a6d684b0d 100644
--- a/client/httpapi/api_test.go
+++ b/client/httpapi/api_test.go
@@ -246,3 +246,31 @@ func Test_NewURLApiWithClient_With_Headers(t *testing.T) {
 		t.Fatal(err)
 	}
 }
+
+func Test_NewURLApiWithClient_HTTP_Variant(t *testing.T) {
+	testcases := []struct {
+		address  string
+		expected string
+	}{
+		{address: "/ip4/127.0.0.1/tcp/80", expected: "http://127.0.0.1:80"},
+		{address: "/ip4/127.0.0.1/tcp/443/tls", expected: "https://127.0.0.1:443"},
+		{address: "/ip4/127.0.0.1/tcp/443/https", expected: "https://127.0.0.1:443"},
+		{address: "/ip4/127.0.0.1/tcp/443/tls/http", expected: "https://127.0.0.1:443"},
+	}
+
+	for _, tc := range testcases {
+		address, err := ma.NewMultiaddr(tc.address)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		api, err := NewApiWithClient(address, &http.Client{})
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		if api.url != tc.expected {
+			t.Errorf("Expected = %s; got %s", tc.expected, api.url)
+		}
+	}
+}
-- 
GitLab