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" '