From c8855828b672b06d272bf095c5cf0809605bc080 Mon Sep 17 00:00:00 2001 From: Marcin Rataj Date: Wed, 18 Oct 2023 19:47:05 +0200 Subject: [PATCH] fix(gw): use real FQDN in DNSLink errors The old version was not very smart and wasted DNS lookup per every inlined DNSLink label (my-v--long-example-com) before retrying with un-inlined one (my.v-long.example.com). This version is optimized to avoid unnecessary DNS lookup for the golden path majority of inlined DNS names on subdomain will hit. It also ensures that in case of missing DNSLink, the un-inlined domain name is used in error path, which makes better UX. --- gateway/hostname.go | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/gateway/hostname.go b/gateway/hostname.go index 758d8499c..a986ef24f 100644 --- a/gateway/hostname.go +++ b/gateway/hostname.go @@ -165,15 +165,32 @@ func NewHostnameHandler(c Config, backend IPFSBackend, next http.Handler) http.H // can be loaded from a subdomain gateway with a wildcard // TLS cert if represented as a single DNS label: // https://my-v--long-example-com.ipns.dweb.link - if ns == "ipns" && !strings.Contains(rootID, ".") { - // if there is no TXT recordfor rootID - if !hasDNSLinkRecord(r.Context(), backend, rootID) { - // my-v--long-example-com → my.v-long.example.com - dnslinkFQDN := toDNSLinkFQDN(rootID) - if hasDNSLinkRecord(r.Context(), backend, dnslinkFQDN) { - // update path prefix to use real FQDN with DNSLink - pathPrefix = "/ipns/" + dnslinkFQDN - } + if ns == "ipns" && !strings.Contains(rootID, ".") && strings.Contains(rootID, "-") { + // If there are no '.' but '-' is present in rootID, we most + // likely have an inlined DNSLink (like my-v--long-example-com) + + // We un-inline and check for DNSLink presence on domain with '.' + // first to minimize the amount of DNS lookups: + // my-v--long-example-com → my.v-long.example.com + dnslinkFQDN := toDNSLinkFQDN(rootID) + + // Does _dnslink.my.v-long.example.com exist? + if hasDNSLinkRecord(r.Context(), backend, dnslinkFQDN) { + // Un-inlined DNS name has a valid DNSLink record. + // Update path prefix to use un-inlined FQDN in gateway processing. + pathPrefix = "/ipns/" + dnslinkFQDN // → /ipns/my.v-long.example.com + + } else if !hasDNSLinkRecord(r.Context(), backend, rootID) { + // Inspected _dnslink.my-v--long-example-com as a + // fallback, but it had no DNSLink record either. + + // At this point it is more likely the un-inlined + // dnslinkFQDN is what the end user wanted to load, so + // we switch to that. This ensures the error message + // about missing DNSLink will use the un-inlined FQDN, + // and not the inlined one. + pathPrefix = "/ipns/" + dnslinkFQDN + } } }