Skip to content

Commit

Permalink
gateway: tests for simpler superfluous namespace handling (ipfs#572)
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias authored and wenyue committed Oct 17, 2024
1 parent a7b9e04 commit 887d48b
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 35 deletions.
86 changes: 86 additions & 0 deletions gateway/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
36 changes: 1 addition & 35 deletions gateway/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"html/template"
"io"
"mime"
"net/http"
Expand Down Expand Up @@ -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(`<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="refresh" content="10;url={{.RedirectURL}}" />
<link rel="canonical" href="{{.RedirectURL}}" />
</head>
<body>
<pre>{{.ErrorMsg}}</pre><pre>(if a redirect does not happen in 10 seconds, use "{{.SuggestedPath}}" instead)</pre>
</body>
</html>`))

type redirectTemplateData struct {
RedirectURL string
SuggestedPath string
ErrorMsg string
}

// handler is a HTTP handler that serves IPFS objects (accessible by default at /ipfs/<path>)
// (it serves requests like GET /ipfs/QmVRzPKPzNtSrEzBFm2UZfxmPAgnaLke4DMcerbsGGSaFe/link)
type handler struct {
Expand Down Expand Up @@ -903,21 +882,8 @@ func (i *handler) handleSuperfluousNamespace(w http.ResponseWriter, r *http.Requ
q, _ := url.ParseQuery(r.URL.RawQuery)
intendedURL = intendedURL + "?" + q.Encode()
}
// return HTTP 400 (Bad Request) with HTML error page that:
// - points at correct canonical path via <link> header
// - displays human-readable error
// - redirects to intendedURL after a short delay

w.WriteHeader(http.StatusBadRequest)
err = redirectTemplate.Execute(w, redirectTemplateData{
RedirectURL: intendedURL,
SuggestedPath: intendedPath.String(),
ErrorMsg: fmt.Sprintf("invalid path: %q should be %q", r.URL.Path, intendedPath.String()),
})
if err != nil {
_, _ = w.Write([]byte(fmt.Sprintf("error during body generation: %v", err)))
}

http.Redirect(w, r, intendedURL, http.StatusMovedPermanently)
return true
}

Expand Down

0 comments on commit 887d48b

Please sign in to comment.