mirror of
https://github.com/ipfs/kubo.git
synced 2025-08-06 19:44:01 +08:00
Fix offline gateway directory logic
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
This commit is contained in:
@ -212,9 +212,8 @@ func (api *CoreAPI) WithOptions(opts ...options.ApiOption) (coreiface.CoreAPI, e
|
|||||||
subApi.recordValidator = nil
|
subApi.recordValidator = nil
|
||||||
|
|
||||||
subApi.exchange = offlinexch.Exchange(subApi.blockstore)
|
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)
|
subApi.dag = dag.NewDAGService(subApi.blocks)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return subApi, nil
|
return subApi, nil
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package iface
|
package iface
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid"
|
||||||
ipfspath "gx/ipfs/QmZErC2Ay6WuGi96CPg316PwitdwgLo6RxZRqVjJjRj2MR/go-path"
|
ipfspath "gx/ipfs/QmZErC2Ay6WuGi96CPg316PwitdwgLo6RxZRqVjJjRj2MR/go-path"
|
||||||
|
|
||||||
cid "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//TODO: merge with ipfspath so we don't depend on it
|
//TODO: merge with ipfspath so we don't depend on it
|
||||||
@ -106,6 +105,12 @@ type resolvedPath struct {
|
|||||||
remainder string
|
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
|
// IpfsPath creates new /ipfs path from the provided CID
|
||||||
func IpfsPath(c cid.Cid) ResolvedPath {
|
func IpfsPath(c cid.Cid) ResolvedPath {
|
||||||
return &resolvedPath{
|
return &resolvedPath{
|
||||||
|
@ -15,6 +15,7 @@ func (tp *provider) TestPath(t *testing.T) {
|
|||||||
t.Run("TestEmptyPathRemainder", tp.TestEmptyPathRemainder)
|
t.Run("TestEmptyPathRemainder", tp.TestEmptyPathRemainder)
|
||||||
t.Run("TestInvalidPathRemainder", tp.TestInvalidPathRemainder)
|
t.Run("TestInvalidPathRemainder", tp.TestInvalidPathRemainder)
|
||||||
t.Run("TestPathRoot", tp.TestPathRoot)
|
t.Run("TestPathRoot", tp.TestPathRoot)
|
||||||
|
t.Run("TestPathJoin", tp.TestPathJoin)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tp *provider) TestMutablePath(t *testing.T) {
|
func (tp *provider) TestMutablePath(t *testing.T) {
|
||||||
@ -165,3 +166,14 @@ func (tp *provider) TestPathRoot(t *testing.T) {
|
|||||||
t.Error("unexpected path cid")
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -119,7 +119,12 @@ func (d *ufsDirectory) Entries() files.DirIterator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *ufsDirectory) Size() (int64, error) {
|
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 {
|
type ufsFile struct {
|
||||||
|
@ -2,13 +2,13 @@ package corehttp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/ipfs/go-ipfs/core/coreapi/interface/options"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
version "github.com/ipfs/go-ipfs"
|
version "github.com/ipfs/go-ipfs"
|
||||||
core "github.com/ipfs/go-ipfs/core"
|
core "github.com/ipfs/go-ipfs/core"
|
||||||
coreapi "github.com/ipfs/go-ipfs/core/coreapi"
|
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"
|
id "gx/ipfs/QmRBaUEQEeFWywfrZJ64QgsmvcqgLSK3VbvGMR2NM2Edpf/go-libp2p/p2p/protocol/identify"
|
||||||
)
|
)
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
gopath "path"
|
gopath "path"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strings"
|
"strings"
|
||||||
@ -26,7 +25,6 @@ import (
|
|||||||
"gx/ipfs/QmZErC2Ay6WuGi96CPg316PwitdwgLo6RxZRqVjJjRj2MR/go-path/resolver"
|
"gx/ipfs/QmZErC2Ay6WuGi96CPg316PwitdwgLo6RxZRqVjJjRj2MR/go-path/resolver"
|
||||||
ft "gx/ipfs/Qmbvw7kpSM2p6rbQ57WGRhhqNfCiNGW6EKH4xgHLw4bsnB/go-unixfs"
|
ft "gx/ipfs/Qmbvw7kpSM2p6rbQ57WGRhhqNfCiNGW6EKH4xgHLw4bsnB/go-unixfs"
|
||||||
"gx/ipfs/Qmbvw7kpSM2p6rbQ57WGRhhqNfCiNGW6EKH4xgHLw4bsnB/go-unixfs/importer"
|
"gx/ipfs/Qmbvw7kpSM2p6rbQ57WGRhhqNfCiNGW6EKH4xgHLw4bsnB/go-unixfs/importer"
|
||||||
uio "gx/ipfs/Qmbvw7kpSM2p6rbQ57WGRhhqNfCiNGW6EKH4xgHLw4bsnB/go-unixfs/io"
|
|
||||||
ipld "gx/ipfs/QmcKKBwfz6FyQdHR2jsXrrF6XeSBXYL86anmWNewpFpoF5/go-ipld-format"
|
ipld "gx/ipfs/QmcKKBwfz6FyQdHR2jsXrrF6XeSBXYL86anmWNewpFpoF5/go-ipld-format"
|
||||||
dag "gx/ipfs/QmdV35UHnL1FM52baPkeUo6u7Fxm2CRUkPTLRPxeF8a4Ap/go-merkledag"
|
dag "gx/ipfs/QmdV35UHnL1FM52baPkeUo6u7Fxm2CRUkPTLRPxeF8a4Ap/go-merkledag"
|
||||||
"gx/ipfs/QmekxXDhCxCJRNuzmHreuaT3BsuJcsjcXWNrtV9C8DRHtd/go-multibase"
|
"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)
|
i.serveFile(w, r, name, modtime, f)
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
dir, ok := dr.(files.Directory)
|
||||||
nd, err := i.api.ResolveNode(ctx, resolvedPath)
|
if !ok {
|
||||||
if err != nil {
|
internalWebError(w, fmt.Errorf("unsupported file type"))
|
||||||
internalWebError(w, err)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dirr, err := uio.NewDirectoryFromNode(i.node.DAG, nd)
|
idx, err := i.api.Unixfs().Get(ctx, coreiface.Join(resolvedPath, "index.html"))
|
||||||
if err != nil {
|
|
||||||
internalWebError(w, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ixnd, err := dirr.Find(ctx, "index.html")
|
|
||||||
switch {
|
switch {
|
||||||
case err == nil:
|
case err == nil:
|
||||||
dirwithoutslash := urlPath[len(urlPath)-1] != '/'
|
dirwithoutslash := urlPath[len(urlPath)-1] != '/'
|
||||||
@ -280,14 +270,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dr, err := i.api.Unixfs().Get(ctx, coreiface.IpfsPath(ixnd.Cid()))
|
f, ok := idx.(files.File)
|
||||||
if err != nil {
|
|
||||||
internalWebError(w, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer dr.Close()
|
|
||||||
|
|
||||||
f, ok := dr.(files.File)
|
|
||||||
if !ok {
|
if !ok {
|
||||||
internalWebError(w, files.ErrNotReader)
|
internalWebError(w, files.ErrNotReader)
|
||||||
return
|
return
|
||||||
@ -297,9 +280,11 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
|
|||||||
http.ServeContent(w, r, "index.html", modtime, f)
|
http.ServeContent(w, r, "index.html", modtime, f)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
|
if _, ok := err.(resolver.ErrNoLink); ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
internalWebError(w, err)
|
internalWebError(w, err)
|
||||||
return
|
return
|
||||||
case os.IsNotExist(err):
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Method == "HEAD" {
|
if r.Method == "HEAD" {
|
||||||
@ -308,12 +293,22 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
|
|||||||
|
|
||||||
// storage for directory listing
|
// storage for directory listing
|
||||||
var dirListing []directoryItem
|
var dirListing []directoryItem
|
||||||
dirr.ForEachLink(ctx, func(link *ipld.Link) error {
|
dirit := dir.Entries()
|
||||||
|
for dirit.Next() {
|
||||||
// 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)}
|
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)
|
dirListing = append(dirListing, di)
|
||||||
return nil
|
}
|
||||||
})
|
if dirit.Err() != nil {
|
||||||
|
internalWebError(w, dirit.Err())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// construct the correct back link
|
// construct the correct back link
|
||||||
// https://github.com/ipfs/go-ipfs/issues/1365
|
// https://github.com/ipfs/go-ipfs/issues/1365
|
||||||
|
@ -233,14 +233,14 @@ test_expect_success "start ipfs nodes" '
|
|||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success "try fetching not present key from node 0" '
|
test_expect_success "try fetching not present key from node 0" '
|
||||||
echo "hi" | ipfsi 1 add -Q > hi.hash &&
|
echo "foo" | ipfsi 1 add -Q > foo.hash &&
|
||||||
test_expect_code 22 curl -f "http://127.0.0.1:$GWPORT/ipfs/$(cat hi.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" '
|
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) &&
|
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" '
|
test_expect_success "stop testbed" '
|
||||||
|
Reference in New Issue
Block a user