提交 afa0c344 作者: Jeromy Johnson 提交者: GitHub

Merge pull request #3897 from ipfs/feat/faster-listing

improved gateway directory listing for sharded nodes
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"os"
gopath "path" gopath "path"
"runtime/debug" "runtime/debug"
"strings" "strings"
...@@ -20,6 +21,7 @@ import ( ...@@ -20,6 +21,7 @@ import (
dagutils "github.com/ipfs/go-ipfs/merkledag/utils" dagutils "github.com/ipfs/go-ipfs/merkledag/utils"
path "github.com/ipfs/go-ipfs/path" path "github.com/ipfs/go-ipfs/path"
ft "github.com/ipfs/go-ipfs/unixfs" ft "github.com/ipfs/go-ipfs/unixfs"
uio "github.com/ipfs/go-ipfs/unixfs/io"
humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize" humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize"
cid "gx/ipfs/QmYhQaCYEcaPPjxJX7YcPcVKkQfRy6sJ7B3XmGFk82XYdQ/go-cid" cid "gx/ipfs/QmYhQaCYEcaPPjxJX7YcPcVKkQfRy6sJ7B3XmGFk82XYdQ/go-cid"
...@@ -227,92 +229,102 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr ...@@ -227,92 +229,102 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
return return
} }
links, err := i.api.Unixfs().Ls(ctx, resolvedPath) nd, err := i.api.ResolveNode(ctx, resolvedPath)
if err != nil { if err != nil {
internalWebError(w, err) internalWebError(w, err)
return return
} }
// storage for directory listing dirr, err := uio.NewDirectoryFromNode(i.node.DAG, nd)
var dirListing []directoryItem if err != nil {
// loop through files internalWebError(w, err)
foundIndex := false return
for _, link := range links { }
if link.Name == "index.html" {
log.Debugf("found index.html link for %s", urlPath)
foundIndex = true
if urlPath[len(urlPath)-1] != '/' {
// See comment above where originalUrlPath is declared.
http.Redirect(w, r, originalUrlPath+"/", 302)
log.Debugf("redirect to %s", originalUrlPath+"/")
return
}
dr, err := i.api.Unixfs().Cat(ctx, coreapi.ParseCid(link.Cid)) ixnd, err := dirr.Find(ctx, "index.html")
if err != nil { switch {
internalWebError(w, err) case err == nil:
return log.Debugf("found index.html link for %s", urlPath)
}
defer dr.Close() if urlPath[len(urlPath)-1] != '/' {
// See comment above where originalUrlPath is declared.
http.Redirect(w, r, originalUrlPath+"/", 302)
log.Debugf("redirect to %s", originalUrlPath+"/")
return
}
// write to request dr, err := i.api.Unixfs().Cat(ctx, coreapi.ParseCid(ixnd.Cid()))
http.ServeContent(w, r, "index.html", modtime, dr) if err != nil {
break internalWebError(w, err)
return
} }
defer dr.Close()
// write to request
http.ServeContent(w, r, "index.html", modtime, dr)
return
default:
internalWebError(w, err)
return
case os.IsNotExist(err):
}
if r.Method == "HEAD" {
return
}
// storage for directory listing
var dirListing []directoryItem
dirr.ForEachLink(ctx, func(link *node.Link) error {
// See comment above where originalUrlPath is declared. // See comment above where originalUrlPath is declared.
di := directoryItem{humanize.Bytes(link.Size), link.Name, gopath.Join(originalUrlPath, link.Name)} di := directoryItem{humanize.Bytes(link.Size), link.Name, gopath.Join(originalUrlPath, link.Name)}
dirListing = append(dirListing, di) dirListing = append(dirListing, di)
} return nil
})
if !foundIndex { // construct the correct back link
if r.Method != "HEAD" { // https://github.com/ipfs/go-ipfs/issues/1365
// construct the correct back link var backLink string = prefix + urlPath
// https://github.com/ipfs/go-ipfs/issues/1365
var backLink string = prefix + urlPath
// don't go further up than /ipfs/$hash/
pathSplit := path.SplitList(backLink)
switch {
// keep backlink
case len(pathSplit) == 3: // url: /ipfs/$hash
// keep backlink
case len(pathSplit) == 4 && pathSplit[3] == "": // url: /ipfs/$hash/
// add the correct link depending on wether the path ends with a slash
default:
if strings.HasSuffix(backLink, "/") {
backLink += "./.."
} else {
backLink += "/.."
}
}
// strip /ipfs/$hash from backlink if IPNSHostnameOption touched the path. // don't go further up than /ipfs/$hash/
if ipnsHostname { pathSplit := path.SplitList(backLink)
backLink = prefix + "/" switch {
if len(pathSplit) > 5 { // keep backlink
// also strip the trailing segment, because it's a backlink case len(pathSplit) == 3: // url: /ipfs/$hash
backLinkParts := pathSplit[3 : len(pathSplit)-2]
backLink += path.Join(backLinkParts) + "/"
}
}
// See comment above where originalUrlPath is declared. // keep backlink
tplData := listingTemplateData{ case len(pathSplit) == 4 && pathSplit[3] == "": // url: /ipfs/$hash/
Listing: dirListing,
Path: originalUrlPath, // add the correct link depending on wether the path ends with a slash
BackLink: backLink, default:
} if strings.HasSuffix(backLink, "/") {
err := listingTemplate.Execute(w, tplData) backLink += "./.."
if err != nil { } else {
internalWebError(w, err) backLink += "/.."
return
}
} }
} }
// strip /ipfs/$hash from backlink if IPNSHostnameOption touched the path.
if ipnsHostname {
backLink = prefix + "/"
if len(pathSplit) > 5 {
// also strip the trailing segment, because it's a backlink
backLinkParts := pathSplit[3 : len(pathSplit)-2]
backLink += path.Join(backLinkParts) + "/"
}
}
// See comment above where originalUrlPath is declared.
tplData := listingTemplateData{
Listing: dirListing,
Path: originalUrlPath,
BackLink: backLink,
}
err = listingTemplate.Execute(w, tplData)
if err != nil {
internalWebError(w, err)
return
}
} }
func (i *gatewayHandler) postHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) { func (i *gatewayHandler) postHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论