Repository: ipfs/boxo

Issue:
Slow responses to requests on 127.0.0.1 when DNSLink enabled
When DNSLink is enabled in kubo (by default), queries to kubo on `127.0.0.1` take longer to respond to than the same queries to `localhost`.

The code in the gateway hostname handler, [here](https://github.com/ipfs/boxo/blob/main/gateway/hostname.go#L24), recognizes `localhost` in the `Host` header, but it does not recognize `127.0.0.1`. This leads it all the way [here](https://github.com/ipfs/boxo/blob/main/gateway/hostname.go#L215) after checking for DNSLink record.

The hostname handler code should recognize IP addresses (both IPv4 and IPv6) and avoid DNSLink lookup for these.

Hints from issue comments:
@gammazero: completed

Solution patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9700470d..b313dd52 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@ The following emojis are used to highlight certain changes:
 
 ### Fixed
 
+- `gateway`: Skip DNSLink lookup for IP addresses to avoid unnecessary DNS queries [#880](https://github.com/ipfs/boxo/pull/880)
 - `bitswap/client`: Fix unintentional ignoring `DontHaveTimeoutConfig` [#872](https://github.com/ipfs/boxo/pull/872)
 
 ### Security
diff --git a/gateway/hostname.go b/gateway/hostname.go
index 29c0b7f8..4c078cec 100644
--- a/gateway/hostname.go
+++ b/gateway/hostname.go
@@ -258,6 +258,11 @@ func isDomainNameAndNotPeerID(hostname string) bool {
 func hasDNSLinkRecord(ctx context.Context, backend IPFSBackend, host string) bool {
 	dnslinkName := stripPort(host)
 
+	// Skip DNSLink lookup for IP addresses
+	if net.ParseIP(dnslinkName) != nil {
+		return false
+	}
+
 	if !isDomainNameAndNotPeerID(dnslinkName) {
 		return false
 	}



Test patch:
diff --git a/gateway/hostname_test.go b/gateway/hostname_test.go
index 1bfb07c4..b6ad366a 100644
--- a/gateway/hostname_test.go
+++ b/gateway/hostname_test.go
@@ -369,3 +369,41 @@ func BenchmarkInlineDNSLink(b *testing.B) {
 		_, _ = InlineDNSLink(testDNSLinkC)
 	}
 }
+
+// Test function for hasDNSLinkRecord with local IP addresses
+func TestHasDNSLinkRecordWithLocalIP(t *testing.T) {
+	t.Parallel()
+
+	// Create test environment
+	backend, _ := newMockBackend(t, "fixtures.car")
+	// Add some DNSLink records to mock backend
+	testCID2, _ := cid.Decode("QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn")
+	backend.namesys["/ipns/example.com"] = newMockNamesysItem(path.FromCid(testCID2), 0)
+
+	ctx := httptest.NewRequest(http.MethodGet, "http://example.com", nil).Context()
+
+	// Test local IP addresses
+	localIPs := []string{
+		"127.0.0.1",
+		"8.8.8.8",
+		"192.168.100.22:8080",
+		"::1",
+		"[::1]:8080",
+		"0:0:0:0:0:0:0:1",
+		"fe80::a89c:baff:fece:8c94",
+	}
+
+	for _, ip := range localIPs {
+		t.Run(ip, func(t *testing.T) {
+			// For local IP addresses, hasDNSLinkRecord should always return false
+			result := hasDNSLinkRecord(ctx, backend, ip)
+			require.False(t, result, "Local IP %s should not attempt DNSLink lookup", ip)
+		})
+	}
+
+	// Test valid domain name
+	t.Run("example.com", func(t *testing.T) {
+		result := hasDNSLinkRecord(ctx, backend, "example.com")
+		require.True(t, result, "example.com should have a valid DNSLink record")
+	})
+}