From 6cee21d39a2f76ea75d487e35230c801c5eff25c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Magiera?= Date: Fri, 4 Jan 2019 02:35:40 +0100 Subject: [PATCH] Fix offline gateway directory logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit License: MIT Signed-off-by: Ɓukasz Magiera --- core/coreapi/coreapi.go | 3 +- core/coreapi/interface/path.go | 9 +++-- core/coreapi/interface/tests/path.go | 12 +++++++ core/coreapi/unixfile.go | 7 +++- core/corehttp/gateway.go | 2 +- core/corehttp/gateway_handler.go | 49 +++++++++++++--------------- test/sharness/t0110-gateway.sh | 8 ++--- 7 files changed, 53 insertions(+), 37 deletions(-) diff --git a/core/coreapi/coreapi.go b/core/coreapi/coreapi.go index d5f6a7a3f13..bea2f05ad28 100644 --- a/core/coreapi/coreapi.go +++ b/core/coreapi/coreapi.go @@ -212,9 +212,8 @@ func (api *CoreAPI) WithOptions(opts ...options.ApiOption) (coreiface.CoreAPI, e subApi.recordValidator = nil subApi.exchange = offlinexch.Exchange(subApi.blockstore) - subApi.blocks = bserv.New(api.blockstore, subApi.exchange) + subApi.blocks = bserv.New(subApi.blockstore, subApi.exchange) subApi.dag = dag.NewDAGService(subApi.blocks) - } return subApi, nil diff --git a/core/coreapi/interface/path.go b/core/coreapi/interface/path.go index 01dda97d5a8..96f30852d84 100644 --- a/core/coreapi/interface/path.go +++ b/core/coreapi/interface/path.go @@ -1,9 +1,8 @@ package iface import ( + "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid" ipfspath "gx/ipfs/QmZErC2Ay6WuGi96CPg316PwitdwgLo6RxZRqVjJjRj2MR/go-path" - - cid "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid" ) //TODO: merge with ipfspath so we don't depend on it @@ -106,6 +105,12 @@ type resolvedPath struct { remainder string } +// Join appends provided segments to the base path +func Join(base Path, a ...string) Path { + s := ipfspath.Join(append([]string{base.String()}, a...)) + return &path{path: ipfspath.FromString(s)} +} + // IpfsPath creates new /ipfs path from the provided CID func IpfsPath(c cid.Cid) ResolvedPath { return &resolvedPath{ diff --git a/core/coreapi/interface/tests/path.go b/core/coreapi/interface/tests/path.go index e74053c0499..7057d628640 100644 --- a/core/coreapi/interface/tests/path.go +++ b/core/coreapi/interface/tests/path.go @@ -15,6 +15,7 @@ func (tp *provider) TestPath(t *testing.T) { t.Run("TestEmptyPathRemainder", tp.TestEmptyPathRemainder) t.Run("TestInvalidPathRemainder", tp.TestInvalidPathRemainder) t.Run("TestPathRoot", tp.TestPathRoot) + t.Run("TestPathJoin", tp.TestPathJoin) } func (tp *provider) TestMutablePath(t *testing.T) { @@ -165,3 +166,14 @@ func (tp *provider) TestPathRoot(t *testing.T) { t.Error("unexpected path cid") } } + +func (tp *provider) TestPathJoin(t *testing.T) { + p1, err := coreiface.ParsePath("/ipfs/QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6/bar/baz") + if err != nil { + t.Error(err) + } + + if coreiface.Join(p1, "foo").String() != "/ipfs/QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6/bar/baz/foo" { + t.Error("unexpected path") + } +} diff --git a/core/coreapi/unixfile.go b/core/coreapi/unixfile.go index 7e4f1782bca..4ddeb771a70 100644 --- a/core/coreapi/unixfile.go +++ b/core/coreapi/unixfile.go @@ -119,7 +119,12 @@ func (d *ufsDirectory) Entries() files.DirIterator { } func (d *ufsDirectory) Size() (int64, error) { - return 0, files.ErrNotSupported + n, err := d.dir.GetNode() + if err != nil { + return 0, err + } + s, err := n.Size() + return int64(s), err } type ufsFile struct { diff --git a/core/corehttp/gateway.go b/core/corehttp/gateway.go index de909a0eff1..105f2436166 100644 --- a/core/corehttp/gateway.go +++ b/core/corehttp/gateway.go @@ -2,13 +2,13 @@ package corehttp import ( "fmt" - "github.com/ipfs/go-ipfs/core/coreapi/interface/options" "net" "net/http" version "github.com/ipfs/go-ipfs" core "github.com/ipfs/go-ipfs/core" coreapi "github.com/ipfs/go-ipfs/core/coreapi" + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options" id "gx/ipfs/QmRBaUEQEeFWywfrZJ64QgsmvcqgLSK3VbvGMR2NM2Edpf/go-libp2p/p2p/protocol/identify" ) diff --git a/core/corehttp/gateway_handler.go b/core/corehttp/gateway_handler.go index 553ebdcf8f5..e80a9fa4539 100644 --- a/core/corehttp/gateway_handler.go +++ b/core/corehttp/gateway_handler.go @@ -7,7 +7,6 @@ import ( "io" "net/http" "net/url" - "os" gopath "path" "runtime/debug" "strings" @@ -26,7 +25,6 @@ import ( "gx/ipfs/QmZErC2Ay6WuGi96CPg316PwitdwgLo6RxZRqVjJjRj2MR/go-path/resolver" ft "gx/ipfs/Qmbvw7kpSM2p6rbQ57WGRhhqNfCiNGW6EKH4xgHLw4bsnB/go-unixfs" "gx/ipfs/Qmbvw7kpSM2p6rbQ57WGRhhqNfCiNGW6EKH4xgHLw4bsnB/go-unixfs/importer" - uio "gx/ipfs/Qmbvw7kpSM2p6rbQ57WGRhhqNfCiNGW6EKH4xgHLw4bsnB/go-unixfs/io" ipld "gx/ipfs/QmcKKBwfz6FyQdHR2jsXrrF6XeSBXYL86anmWNewpFpoF5/go-ipld-format" dag "gx/ipfs/QmdV35UHnL1FM52baPkeUo6u7Fxm2CRUkPTLRPxeF8a4Ap/go-merkledag" "gx/ipfs/QmekxXDhCxCJRNuzmHreuaT3BsuJcsjcXWNrtV9C8DRHtd/go-multibase" @@ -254,22 +252,14 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr } i.serveFile(w, r, name, modtime, f) return - - } - - nd, err := i.api.ResolveNode(ctx, resolvedPath) - if err != nil { - internalWebError(w, err) - return } - - dirr, err := uio.NewDirectoryFromNode(i.node.DAG, nd) - if err != nil { - internalWebError(w, err) + dir, ok := dr.(files.Directory) + if !ok { + internalWebError(w, fmt.Errorf("unsupported file type")) return } - ixnd, err := dirr.Find(ctx, "index.html") + idx, err := i.api.Unixfs().Get(ctx, coreiface.Join(resolvedPath, "index.html")) switch { case err == nil: dirwithoutslash := urlPath[len(urlPath)-1] != '/' @@ -280,14 +270,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr return } - dr, err := i.api.Unixfs().Get(ctx, coreiface.IpfsPath(ixnd.Cid())) - if err != nil { - internalWebError(w, err) - return - } - defer dr.Close() - - f, ok := dr.(files.File) + f, ok := idx.(files.File) if !ok { internalWebError(w, files.ErrNotReader) return @@ -297,9 +280,11 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr http.ServeContent(w, r, "index.html", modtime, f) return default: + if _, ok := err.(resolver.ErrNoLink); ok { + break + } internalWebError(w, err) return - case os.IsNotExist(err): } if r.Method == "HEAD" { @@ -308,12 +293,22 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr // storage for directory listing var dirListing []directoryItem - dirr.ForEachLink(ctx, func(link *ipld.Link) error { + dirit := dir.Entries() + for dirit.Next() { // See comment above where originalUrlPath is declared. - di := directoryItem{humanize.Bytes(link.Size), link.Name, gopath.Join(originalUrlPath, link.Name)} + s, err := dirit.Node().Size() + if err != nil { + internalWebError(w, err) + return + } + + di := directoryItem{humanize.Bytes(uint64(s)), dirit.Name(), gopath.Join(originalUrlPath, dirit.Name())} dirListing = append(dirListing, di) - return nil - }) + } + if dirit.Err() != nil { + internalWebError(w, dirit.Err()) + return + } // construct the correct back link // https://github.com/ipfs/go-ipfs/issues/1365 diff --git a/test/sharness/t0110-gateway.sh b/test/sharness/t0110-gateway.sh index 9b2f6430ef9..26686ccc48c 100755 --- a/test/sharness/t0110-gateway.sh +++ b/test/sharness/t0110-gateway.sh @@ -233,14 +233,14 @@ test_expect_success "start ipfs nodes" ' ' test_expect_success "try fetching not present key from node 0" ' - echo "hi" | ipfsi 1 add -Q > hi.hash && - test_expect_code 22 curl -f "http://127.0.0.1:$GWPORT/ipfs/$(cat hi.hash)" + echo "foo" | ipfsi 1 add -Q > foo.hash && + test_expect_code 22 curl -f "http://127.0.0.1:$GWPORT/ipfs/$(cat foo.hash)" ' test_expect_success "try fetching present key from from node 0" ' - echo "hi" | ipfsi 0 add -Q > hi.hash && + echo "bar" | ipfsi 0 add -Q > bar.hash && PORT1=$(ipfs config Addresses.Gateway | cut -d/ -f 5) && - curl -f "http://127.0.0.1:$GWPORT/ipfs/$(cat hi.hash)" + curl -f "http://127.0.0.1:$GWPORT/ipfs/$(cat bar.hash)" ' test_expect_success "stop testbed" '