diff --git a/gateway/gateway_test.go b/gateway/gateway_test.go index 4785ec7598..031a184a54 100644 --- a/gateway/gateway_test.go +++ b/gateway/gateway_test.go @@ -577,6 +577,92 @@ func TestRedirects(t *testing.T) { do(http.MethodGet) do(http.MethodHead) }) + + t.Run("Superfluous namespace", func(t *testing.T) { + t.Parallel() + + backend, root := newMockBackend(t, "fixtures.car") + backend.namesys["/ipns/dnslink-gateway.com"] = newMockNamesysItem(path.FromCid(root), 0) + backend.namesys["/ipns/dnslink-website.com"] = newMockNamesysItem(path.FromCid(root), 0) + + ts := newTestServerWithConfig(t, backend, Config{ + NoDNSLink: false, + PublicGateways: map[string]*PublicGateway{ + "dnslink-gateway.com": { + Paths: []string{"/ipfs", "/ipns"}, + NoDNSLink: false, + DeserializedResponses: true, + }, + "dnslink-website.com": { + Paths: []string{}, + NoDNSLink: false, + DeserializedResponses: true, + }, + "gateway.com": { + Paths: []string{"/ipfs"}, + UseSubdomains: false, + NoDNSLink: true, + DeserializedResponses: true, + }, + "subdomain-gateway.com": { + Paths: []string{"/ipfs", "/ipns"}, + UseSubdomains: true, + NoDNSLink: true, + DeserializedResponses: true, + }, + }, + DeserializedResponses: true, + }) + + for _, test := range []struct { + host string + path string + status int + location string + }{ + // Barebones gateway + {"", "/ipfs/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR", http.StatusMovedPermanently, "/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"}, + {"", "/ipfs/ipns/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR", http.StatusMovedPermanently, "/ipns/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"}, + {"", "/ipfs/ipns/dnslink.com", http.StatusMovedPermanently, "/ipns/dnslink.com"}, + + // DNSLink Gateway with /ipfs and /ipns enabled + {"dnslink-gateway.com", "/ipfs/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR", http.StatusMovedPermanently, "/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"}, + {"dnslink-gateway.com", "/ipfs/ipns/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR", http.StatusMovedPermanently, "/ipns/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"}, + {"dnslink-gateway.com", "/ipfs/ipns/dnslink.com", http.StatusMovedPermanently, "/ipns/dnslink.com"}, + + // DNSLink Gateway without /ipfs and /ipns + {"dnslink-website.com", "/ipfs/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR", http.StatusNotFound, ""}, + {"dnslink-website.com", "/ipfs/ipns/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR", http.StatusNotFound, ""}, + {"dnslink-website.com", "/ipfs/ipns/dnslink.com", http.StatusNotFound, ""}, + + // Public gateway + {"gateway.com", "/ipfs/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR", http.StatusMovedPermanently, "/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"}, + {"gateway.com", "/ipfs/ipns/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR", http.StatusMovedPermanently, "/ipns/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"}, + {"gateway.com", "/ipfs/ipns/dnslink.com", http.StatusMovedPermanently, "/ipns/dnslink.com"}, + + // Subdomain gateway + {"subdomain-gateway.com", "/ipfs/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR", http.StatusMovedPermanently, "/ipfs/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"}, + {"subdomain-gateway.com", "/ipfs/ipns/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR", http.StatusMovedPermanently, "/ipns/QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR"}, + {"subdomain-gateway.com", "/ipfs/ipns/dnslink.com", http.StatusMovedPermanently, "/ipns/dnslink.com"}, + } { + testName := ts.URL + test.path + if test.host != "" { + testName += " " + test.host + } + + t.Run(testName, func(t *testing.T) { + req := mustNewRequest(t, http.MethodGet, ts.URL+test.path, nil) + req.Header.Set("Accept", "text/html") + if test.host != "" { + req.Host = test.host + } + resp := mustDoWithoutRedirect(t, req) + defer resp.Body.Close() + require.Equal(t, test.status, resp.StatusCode) + require.Equal(t, test.location, resp.Header.Get("Location")) + }) + } + }) } func TestDeserializedResponses(t *testing.T) { diff --git a/gateway/handler.go b/gateway/handler.go index a64d229716..6963bdebfd 100644 --- a/gateway/handler.go +++ b/gateway/handler.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "html/template" "io" "mime" "net/http" @@ -43,26 +42,6 @@ var ( noModtime = time.Unix(0, 0) // disables Last-Modified header if passed as modtime ) -// HTML-based redirect for errors which can be recovered from, but we want -// to provide hint to people that they should fix things on their end. -var redirectTemplate = template.Must(template.New("redirect").Parse(` - -
- - - - - -{{.ErrorMsg}}
(if a redirect does not happen in 10 seconds, use "{{.SuggestedPath}}" instead)- -`)) - -type redirectTemplateData struct { - RedirectURL string - SuggestedPath string - ErrorMsg string -} - // handler is a HTTP handler that serves IPFS objects (accessible by default at /ipfs/