1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-06-29 17:36:38 +08:00

gateway: re-use resolved path

Instead of resolving a node, we resolve a path. This resolved path
is then re-used for Cat and Ls. This way, a resolve operation is
only done once.

The error messages for a failed resolve is changed from `ipfs cat …`
to `ipfs resolve …` to better reflect the API calls. The test is
updated accordingly.

License: MIT
Signed-off-by: Remco Bloemen <remco@2π.com>
This commit is contained in:
Remco Bloemen
2017-04-18 17:22:01 +01:00
parent 8db6f86de6
commit a90f4967e3
2 changed files with 19 additions and 18 deletions

View File

@ -164,7 +164,22 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
return return
} }
dr, err := i.api.Unixfs().Cat(ctx, parsedPath) // Resolve path to the final DAG node for the ETag
resolvedPath, err := i.api.ResolvePath(ctx, parsedPath)
switch err {
case nil:
case coreiface.ErrOffline:
if !i.node.OnlineMode() {
webError(w, "ipfs resolve -r "+urlPath, err, http.StatusServiceUnavailable)
return
}
fallthrough
default:
webError(w, "ipfs resolve -r "+urlPath, err, http.StatusNotFound)
return
}
dr, err := i.api.Unixfs().Cat(ctx, resolvedPath)
dir := false dir := false
switch err { switch err {
case nil: case nil:
@ -172,27 +187,13 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
defer dr.Close() defer dr.Close()
case coreiface.ErrIsDir: case coreiface.ErrIsDir:
dir = true dir = true
case coreiface.ErrOffline:
if !i.node.OnlineMode() {
webError(w, "ipfs cat "+urlPath, err, http.StatusServiceUnavailable)
return
}
fallthrough
default: default:
webError(w, "ipfs cat "+urlPath, err, http.StatusNotFound) webError(w, "ipfs cat "+urlPath, err, http.StatusNotFound)
return return
} }
// Resolve path to the final DAG node for the ETag
dagnode, err := i.api.ResolveNode(ctx, parsedPath)
if err != nil {
// Unixfs().Cat() also calls ResolveNode, so it should not fail here.
webError(w, "could not resolve ipfs path", err, http.StatusBadRequest)
return
}
// Check etag send back to us // Check etag send back to us
etag := "\"" + dagnode.Cid().String() + "\"" etag := "\"" + resolvedPath.Cid().String() + "\""
if r.Header.Get("If-None-Match") == etag { if r.Header.Get("If-None-Match") == etag {
w.WriteHeader(http.StatusNotModified) w.WriteHeader(http.StatusNotModified)
return return
@ -225,7 +226,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
return return
} }
links, err := i.api.Unixfs().Ls(ctx, parsedPath) links, err := i.api.Unixfs().Ls(ctx, resolvedPath)
if err != nil { if err != nil {
internalWebError(w, err) internalWebError(w, err)
return return

View File

@ -136,7 +136,7 @@ func TestGatewayGet(t *testing.T) {
{"localhost:5001", "/", http.StatusNotFound, "404 page not found\n"}, {"localhost:5001", "/", http.StatusNotFound, "404 page not found\n"},
{"localhost:5001", "/" + k, http.StatusNotFound, "404 page not found\n"}, {"localhost:5001", "/" + k, http.StatusNotFound, "404 page not found\n"},
{"localhost:5001", "/ipfs/" + k, http.StatusOK, "fnord"}, {"localhost:5001", "/ipfs/" + k, http.StatusOK, "fnord"},
{"localhost:5001", "/ipns/nxdomain.example.com", http.StatusNotFound, "ipfs cat /ipns/nxdomain.example.com: " + namesys.ErrResolveFailed.Error() + "\n"}, {"localhost:5001", "/ipns/nxdomain.example.com", http.StatusNotFound, "ipfs resolve -r /ipns/nxdomain.example.com: " + namesys.ErrResolveFailed.Error() + "\n"},
{"localhost:5001", "/ipns/example.com", http.StatusOK, "fnord"}, {"localhost:5001", "/ipns/example.com", http.StatusOK, "fnord"},
{"example.com", "/", http.StatusOK, "fnord"}, {"example.com", "/", http.StatusOK, "fnord"},
} { } {