mirror of
https://github.com/ipfs/kubo.git
synced 2026-03-06 00:38:08 +08:00
fix(gateway): correct breadcrumbs on dnslink site
This commit is contained in:
parent
a6c1598612
commit
cd1feb3af4
@ -379,8 +379,9 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
|
||||
|
||||
hash := resolvedPath.Cid().String()
|
||||
|
||||
// Storage for gateway URL to be used when linking to other rootIDs. This
|
||||
// will be blank unless subdomain resolution is being used for this request.
|
||||
// Gateway root URL to be used when linking to other rootIDs.
|
||||
// This will be blank unless subdomain or DNSLink resolution is being used
|
||||
// for this request.
|
||||
var gwURL string
|
||||
|
||||
// Get gateway hostname and build gateway URL.
|
||||
@ -396,11 +397,15 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
|
||||
Listing: dirListing,
|
||||
Size: size,
|
||||
Path: urlPath,
|
||||
Breadcrumbs: breadcrumbs(urlPath),
|
||||
Breadcrumbs: breadcrumbs(urlPath, gwURL),
|
||||
BackLink: backLink,
|
||||
Hash: hash,
|
||||
}
|
||||
|
||||
// TODO: remove logging below
|
||||
// tplDataJSON, _ := json.MarshalIndent(tplData, "", " ")
|
||||
// fmt.Println(string(tplDataJSON))
|
||||
|
||||
err = listingTemplate.Execute(w, tplData)
|
||||
if err != nil {
|
||||
internalWebError(w, err)
|
||||
|
||||
@ -34,7 +34,7 @@ type breadcrumb struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
func breadcrumbs(urlPath string) []breadcrumb {
|
||||
func breadcrumbs(urlPath string, gwRootURL string) []breadcrumb {
|
||||
var ret []breadcrumb
|
||||
|
||||
p, err := ipfspath.ParsePath(urlPath)
|
||||
@ -42,8 +42,9 @@ func breadcrumbs(urlPath string) []breadcrumb {
|
||||
// No breadcrumbs, fallback to bare Path in template
|
||||
return ret
|
||||
}
|
||||
|
||||
segs := p.Segments()
|
||||
ns := segs[0]
|
||||
contentRoot := segs[1]
|
||||
for i, seg := range segs {
|
||||
if i == 0 {
|
||||
ret = append(ret, breadcrumb{Name: seg})
|
||||
@ -55,6 +56,20 @@ func breadcrumbs(urlPath string) []breadcrumb {
|
||||
}
|
||||
}
|
||||
|
||||
// Drop the /ipns/<fqdn> prefix from breadcrumb Paths when directory listing
|
||||
// on a DNSLink website (loaded due to Host header in HTTP request).
|
||||
// Necessary because gwRootURL won't have a public gateway mounted.
|
||||
if ns == "ipns" && (("//" + contentRoot) == gwRootURL) {
|
||||
prefix := "/ipns/" + contentRoot
|
||||
for i, crumb := range ret {
|
||||
if strings.HasPrefix(crumb.Path, prefix) {
|
||||
ret[i].Path = strings.Replace(crumb.Path, prefix, "", 1)
|
||||
}
|
||||
}
|
||||
// Make contentRoot breadcrumb link to the website root
|
||||
ret[1].Path = "/"
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
@ -391,6 +391,8 @@ func TestIPNSHostnameRedirect(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test directory listing on DNSLink website
|
||||
// (scenario when Host header is the same as URL hostname)
|
||||
func TestIPNSHostnameBacklinks(t *testing.T) {
|
||||
ns := mockNamesys{}
|
||||
ts, api, ctx := newTestServerAndNode(t, ns)
|
||||
@ -445,7 +447,7 @@ func TestIPNSHostnameBacklinks(t *testing.T) {
|
||||
s := string(body)
|
||||
t.Logf("body: %s\n", string(body))
|
||||
|
||||
if !matchPathOrBreadcrumbs(s, "/ipns/<a href=\"/ipns/example.net\">example.net</a>/<a href=\"/ipns/example.net/foo%3F%20%23%3C%27\">foo? #<'</a>") {
|
||||
if !matchPathOrBreadcrumbs(s, "/ipns/<a href=\"//example.net/\">example.net</a>/<a href=\"//example.net/foo%3F%20%23%3C%27\">foo? #<'</a>") {
|
||||
t.Fatalf("expected a path in directory listing")
|
||||
}
|
||||
if !strings.Contains(s, "<a href=\"/foo%3F%20%23%3C%27/./..\">") {
|
||||
@ -511,7 +513,7 @@ func TestIPNSHostnameBacklinks(t *testing.T) {
|
||||
s = string(body)
|
||||
t.Logf("body: %s\n", string(body))
|
||||
|
||||
if !matchPathOrBreadcrumbs(s, "/ipns/<a href=\"/ipns/example.net\">example.net</a>/<a href=\"/ipns/example.net/foo%3F%20%23%3C%27\">foo? #<'</a>/<a href=\"/ipns/example.net/foo%3F%20%23%3C%27/bar\">bar</a>") {
|
||||
if !matchPathOrBreadcrumbs(s, "/ipns/<a href=\"//example.net/\">example.net</a>/<a href=\"//example.net/foo%3F%20%23%3C%27\">foo? #<'</a>/<a href=\"//example.net/foo%3F%20%23%3C%27/bar\">bar</a>") {
|
||||
t.Fatalf("expected a path in directory listing")
|
||||
}
|
||||
if !strings.Contains(s, "<a href=\"/foo%3F%20%23%3C%27/bar/./..\">") {
|
||||
@ -545,7 +547,7 @@ func TestIPNSHostnameBacklinks(t *testing.T) {
|
||||
s = string(body)
|
||||
t.Logf("body: %s\n", string(body))
|
||||
|
||||
if !matchPathOrBreadcrumbs(s, "/ipns/<a href=\"/ipns/example.net\">example.net</a>") {
|
||||
if !matchPathOrBreadcrumbs(s, "/ipns/<a href=\"//example.net/\">example.net</a>") {
|
||||
t.Fatalf("expected a path in directory listing")
|
||||
}
|
||||
if !strings.Contains(s, "<a href=\"/good-prefix/\">") {
|
||||
|
||||
@ -129,7 +129,7 @@ func HostnameOption() ServeOption {
|
||||
if !gw.NoDNSLink && isDNSLinkRequest(r.Context(), coreAPI, host) {
|
||||
// rewrite path and handle as DNSLink
|
||||
r.URL.Path = "/ipns/" + stripPort(host) + r.URL.Path
|
||||
childMux.ServeHTTP(w, r)
|
||||
childMux.ServeHTTP(w, withHostnameContext(r, host))
|
||||
return
|
||||
}
|
||||
|
||||
@ -143,10 +143,6 @@ func HostnameOption() ServeOption {
|
||||
if gw, hostname, ns, rootID, ok := knownSubdomainDetails(host, knownGateways); ok {
|
||||
// Looks like we're using a known gateway in subdomain mode.
|
||||
|
||||
// Add gateway hostname context for linking to other root ids.
|
||||
// Example: localhost/ipfs/{cid}
|
||||
ctx := context.WithValue(r.Context(), "gw-hostname", hostname)
|
||||
|
||||
// Assemble original path prefix.
|
||||
pathPrefix := "/" + ns + "/" + rootID
|
||||
|
||||
@ -201,7 +197,7 @@ func HostnameOption() ServeOption {
|
||||
r.URL.Path = pathPrefix + r.URL.Path
|
||||
|
||||
// Serve path request
|
||||
childMux.ServeHTTP(w, r.WithContext(ctx))
|
||||
childMux.ServeHTTP(w, withHostnameContext(r, hostname))
|
||||
return
|
||||
}
|
||||
// We don't have a known gateway. Fallback on DNSLink lookup
|
||||
@ -213,7 +209,7 @@ func HostnameOption() ServeOption {
|
||||
if !cfg.Gateway.NoDNSLink && isDNSLinkRequest(r.Context(), coreAPI, host) {
|
||||
// rewrite path and handle as DNSLink
|
||||
r.URL.Path = "/ipns/" + stripPort(host) + r.URL.Path
|
||||
childMux.ServeHTTP(w, r)
|
||||
childMux.ServeHTTP(w, withHostnameContext(r, host))
|
||||
return
|
||||
}
|
||||
|
||||
@ -234,6 +230,17 @@ type wildcardHost struct {
|
||||
spec *config.GatewaySpec
|
||||
}
|
||||
|
||||
// Extends request context to include hostname of a canonical gateway root
|
||||
// (subdomain root or dnslink fqdn)
|
||||
func withHostnameContext(r *http.Request, hostname string) *http.Request {
|
||||
// This is required for links on directory listing pages to work correctly
|
||||
// on subdomain and dnslink gateways. While DNSlink could read value from
|
||||
// Host header, subdomain gateways have more comples rules (knownSubdomainDetails)
|
||||
// More: https://github.com/ipfs/dir-index-html/issues/42
|
||||
ctx := context.WithValue(r.Context(), "gw-hostname", hostname)
|
||||
return r.WithContext(ctx)
|
||||
}
|
||||
|
||||
func prepareKnownGateways(publicGateways map[string]*config.GatewaySpec) gatewayHosts {
|
||||
var hosts gatewayHosts
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user