@cryptotaxi247 / kubo / commits / 6cee21d39

Fix offline gateway directory logic

License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>

Łukasz Magiera committed Jan 4, 2019 at 02:35 UTC 6cee21d39a2f76ea75d487e35230c801c5eff25c
7 files changed +53 -37
core/coreapi/coreapi.go
+1 -2
@@ -212,9 +212,8 @@ func (api *CoreAPI) WithOptions(opts ...options.ApiOption) (coreiface.CoreAPI, e
212 subApi.recordValidator = nil
213
214 subApi.exchange = offlinexch.Exchange(subApi.blockstore)
215 - subApi.blocks = bserv.New(api.blockstore, subApi.exchange)
215 + subApi.blocks = bserv.New(subApi.blockstore, subApi.exchange)
216 subApi.dag = dag.NewDAGService(subApi.blocks)
217 -
217 }
218
219 return subApi, nil
core/coreapi/interface/path.go
+7 -2
@@ -1,9 +1,8 @@
1 package iface
2
3 import (
4 + "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid"
5 ipfspath "gx/ipfs/QmZErC2Ay6WuGi96CPg316PwitdwgLo6RxZRqVjJjRj2MR/go-path"
5 -
6 - cid "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid"
6 )
7
8 //TODO: merge with ipfspath so we don't depend on it
@@ -106,6 +105,12 @@ type resolvedPath struct {
105 remainder string
106 }
107
108 +// Join appends provided segments to the base path
109 +func Join(base Path, a ...string) Path {
110 + s := ipfspath.Join(append([]string{base.String()}, a...))
111 + return &path{path: ipfspath.FromString(s)}
112 +}
113 +
114 // IpfsPath creates new /ipfs path from the provided CID
115 func IpfsPath(c cid.Cid) ResolvedPath {
116 return &resolvedPath{
core/coreapi/interface/tests/path.go
+12
@@ -15,6 +15,7 @@ func (tp *provider) TestPath(t *testing.T) {
15 t.Run("TestEmptyPathRemainder", tp.TestEmptyPathRemainder)
16 t.Run("TestInvalidPathRemainder", tp.TestInvalidPathRemainder)
17 t.Run("TestPathRoot", tp.TestPathRoot)
18 + t.Run("TestPathJoin", tp.TestPathJoin)
19 }
20
21 func (tp *provider) TestMutablePath(t *testing.T) {
@@ -165,3 +166,14 @@ func (tp *provider) TestPathRoot(t *testing.T) {
166 t.Error("unexpected path cid")
167 }
168 }
169 +
170 +func (tp *provider) TestPathJoin(t *testing.T) {
171 + p1, err := coreiface.ParsePath("/ipfs/QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6/bar/baz")
172 + if err != nil {
173 + t.Error(err)
174 + }
175 +
176 + if coreiface.Join(p1, "foo").String() != "/ipfs/QmYNmQKp6SuaVrpgWRsPTgCQCnpxUYGq76YEKBXuj2N4H6/bar/baz/foo" {
177 + t.Error("unexpected path")
178 + }
179 +}
core/coreapi/unixfile.go
+6 -1
@@ -119,7 +119,12 @@ func (d *ufsDirectory) Entries() files.DirIterator {
119 }
120
121 func (d *ufsDirectory) Size() (int64, error) {
122 - return 0, files.ErrNotSupported
122 + n, err := d.dir.GetNode()
123 + if err != nil {
124 + return 0, err
125 + }
126 + s, err := n.Size()
127 + return int64(s), err
128 }
129
130 type ufsFile struct {
core/corehttp/gateway.go
+1 -1
@@ -2,13 +2,13 @@ package corehttp
2
3 import (
4 "fmt"
5 - "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
5 "net"
6 "net/http"
7
8 version "github.com/ipfs/go-ipfs"
9 core "github.com/ipfs/go-ipfs/core"
10 coreapi "github.com/ipfs/go-ipfs/core/coreapi"
11 + options "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
12
13 id "gx/ipfs/QmRBaUEQEeFWywfrZJ64QgsmvcqgLSK3VbvGMR2NM2Edpf/go-libp2p/p2p/protocol/identify"
14 )
core/corehttp/gateway_handler.go
+22 -27
@@ -7,7 +7,6 @@ import (
7 "io"
8 "net/http"
9 "net/url"
10 - "os"
10 gopath "path"
11 "runtime/debug"
12 "strings"
@@ -26,7 +25,6 @@ import (
25 "gx/ipfs/QmZErC2Ay6WuGi96CPg316PwitdwgLo6RxZRqVjJjRj2MR/go-path/resolver"
26 ft "gx/ipfs/Qmbvw7kpSM2p6rbQ57WGRhhqNfCiNGW6EKH4xgHLw4bsnB/go-unixfs"
27 "gx/ipfs/Qmbvw7kpSM2p6rbQ57WGRhhqNfCiNGW6EKH4xgHLw4bsnB/go-unixfs/importer"
29 - uio "gx/ipfs/Qmbvw7kpSM2p6rbQ57WGRhhqNfCiNGW6EKH4xgHLw4bsnB/go-unixfs/io"
28 ipld "gx/ipfs/QmcKKBwfz6FyQdHR2jsXrrF6XeSBXYL86anmWNewpFpoF5/go-ipld-format"
29 dag "gx/ipfs/QmdV35UHnL1FM52baPkeUo6u7Fxm2CRUkPTLRPxeF8a4Ap/go-merkledag"
30 "gx/ipfs/QmekxXDhCxCJRNuzmHreuaT3BsuJcsjcXWNrtV9C8DRHtd/go-multibase"
@@ -254,22 +252,14 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
252 }
253 i.serveFile(w, r, name, modtime, f)
254 return
257 -
258 - }
259 -
260 - nd, err := i.api.ResolveNode(ctx, resolvedPath)
261 - if err != nil {
262 - internalWebError(w, err)
263 - return
255 }
265 -
266 - dirr, err := uio.NewDirectoryFromNode(i.node.DAG, nd)
267 - if err != nil {
268 - internalWebError(w, err)
256 + dir, ok := dr.(files.Directory)
257 + if !ok {
258 + internalWebError(w, fmt.Errorf("unsupported file type"))
259 return
260 }
261
272 - ixnd, err := dirr.Find(ctx, "index.html")
262 + idx, err := i.api.Unixfs().Get(ctx, coreiface.Join(resolvedPath, "index.html"))
263 switch {
264 case err == nil:
265 dirwithoutslash := urlPath[len(urlPath)-1] != '/'
@@ -280,14 +270,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
270 return
271 }
272
283 - dr, err := i.api.Unixfs().Get(ctx, coreiface.IpfsPath(ixnd.Cid()))
284 - if err != nil {
285 - internalWebError(w, err)
286 - return
287 - }
288 - defer dr.Close()
289 -
290 - f, ok := dr.(files.File)
273 + f, ok := idx.(files.File)
274 if !ok {
275 internalWebError(w, files.ErrNotReader)
276 return
@@ -297,9 +280,11 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
280 http.ServeContent(w, r, "index.html", modtime, f)
281 return
282 default:
283 + if _, ok := err.(resolver.ErrNoLink); ok {
284 + break
285 + }
286 internalWebError(w, err)
287 return
302 - case os.IsNotExist(err):
288 }
289
290 if r.Method == "HEAD" {
@@ -308,12 +293,22 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
293
294 // storage for directory listing
295 var dirListing []directoryItem
311 - dirr.ForEachLink(ctx, func(link *ipld.Link) error {
296 + dirit := dir.Entries()
297 + for dirit.Next() {
298 // See comment above where originalUrlPath is declared.
313 - di := directoryItem{humanize.Bytes(link.Size), link.Name, gopath.Join(originalUrlPath, link.Name)}
299 + s, err := dirit.Node().Size()
300 + if err != nil {
301 + internalWebError(w, err)
302 + return
303 + }
304 +
305 + di := directoryItem{humanize.Bytes(uint64(s)), dirit.Name(), gopath.Join(originalUrlPath, dirit.Name())}
306 dirListing = append(dirListing, di)
315 - return nil
316 - })
307 + }
308 + if dirit.Err() != nil {
309 + internalWebError(w, dirit.Err())
310 + return
311 + }
312
313 // construct the correct back link
314 // https://github.com/ipfs/go-ipfs/issues/1365
test/sharness/t0110-gateway.sh
+4 -4
@@ -233,14 +233,14 @@ test_expect_success "start ipfs nodes" '
233 '
234
235 test_expect_success "try fetching not present key from node 0" '
236 - echo "hi" | ipfsi 1 add -Q > hi.hash &&
237 - test_expect_code 22 curl -f "http://127.0.0.1:$GWPORT/ipfs/$(cat hi.hash)"
236 + echo "foo" | ipfsi 1 add -Q > foo.hash &&
237 + test_expect_code 22 curl -f "http://127.0.0.1:$GWPORT/ipfs/$(cat foo.hash)"
238 '
239
240 test_expect_success "try fetching present key from from node 0" '
241 - echo "hi" | ipfsi 0 add -Q > hi.hash &&
241 + echo "bar" | ipfsi 0 add -Q > bar.hash &&
242 PORT1=$(ipfs config Addresses.Gateway | cut -d/ -f 5) &&
243 - curl -f "http://127.0.0.1:$GWPORT/ipfs/$(cat hi.hash)"
243 + curl -f "http://127.0.0.1:$GWPORT/ipfs/$(cat bar.hash)"
244 '
245
246 test_expect_success "stop testbed" '